Tabellenstruktur/Konzeptfrage
Matze
- datenbank
1 Vinzenz Mai0 Matze0 hawkmaster0 Matze
0 Vinzenz Mai0 Matze0 Vinzenz Mai0 Matze
0 hawkmaster0 Matze
1 Cheatah
Hallo!
Ich hab eine Frage wie ich 2 MySQL Tabellen am besten miteinander verknüpfen soll.
Ich habe eine Tabelle A in der, je nach Situation, Märkte gespeichert oder entfernt werden.
Die Tabelle hat mehrere Spalten, darunter Name, Anschrift... , eine ID.
Ich habe eine Tabelle B in der Produkte eingetragen und ggf. wieder entfernt werden.
Ebenfalls mit mehreren Spalten: Name, Hersteller... , ID.
Die Produkte sollen beim Eintragen verschiedenen Märkten zugeordnet werden.
Z.B. "Quark" mit ID 1 aus der Tabelle B gibt es im "Tante Emma Laden" mit der ID 6 und bei "Steffens Eck" mit der ID 7 aus der Tabelle A.
Wenn ein Markt aus Tabelle A gelöscht wird, soll auch dessen Zuordnung bei den Produkten entfernt werden.
Meine Frage ist, wie ich die Zuordnung am besten speichern soll?
Sollte ich in der Produktetabelle eine Spalte anlegen in der sämtliche verfügbaren Märkte kommasepariert gelistet sind?
Das dürfte mir Probleme machen wenn ich einen Markt lösche und dann jedes Produkt nach dessen Zuordnung durchsuchen muss um diese ebenfalls zu ändern.
Daher habe ich überlegt eine dritte Tabelle anzulegen in der die Zuordnung geregelt wird.
Nur wie muss die Struktur der Tabelle aussehen?
Da die Anzahl der Märkte und Produkte varriert, kann ich beides nicht als Spalte nehmen.
Meine Idee ist jetzt eine Tabelle C mit 2 Spalten.
Eine Spalte mit der ID vom Markt oder des Produkts und eine Spalte wieder mit einer kommaseparierten Liste des Gegenstücks.
Das Problem dabei ist aber, dass ich in dem Fall immer die komplette Tabelle durchsuchen muss wenn ich einen Artikel oder einen Markt lösche um die Zuordnungen bei allen anderen Märkten oder Artikeln entsprechend zu ändern.
Komplizierter wird es dann noch, wenn ich einen Markt lösche, ein Produkt dadurch ohne Zuordnung dasteht und dashalb ebenfalls gelöscht werden muss.
Ich hoffe ich hab mich verständlich ausgedrückt.
Wie löst man sowas also in der Praxis am besten?
Danke für Hilfe!
Grüße, Matze
Hallo,
Ich hab eine Frage wie ich 2 MySQL Tabellen am besten miteinander verknüpfen soll.
Die Produkte sollen beim Eintragen verschiedenen Märkten zugeordnet werden.
Z.B. "Quark" mit ID 1 aus der Tabelle B gibt es im "Tante Emma Laden" mit der ID 6 und bei "Steffens Eck" mit der ID 7 aus der Tabelle A.
ein Produkt kann es bei mehreren Märkten geben,
ein Markt kann mehrere Produkte führen,
=> das ist eine n:m-Beziehung, die Du in MySQL mit einer Beziehungstabelle
umsetzen solltest.
Wenn ein Markt aus Tabelle A gelöscht wird, soll auch dessen Zuordnung bei den Produkten entfernt werden.
So etwas löst man in Datenbankmanagementsystemen mit Foreign-Key-Constraints und ON DELETE CASCADE. MySQL kann das, aber nicht mit jeder Tabellenengine. MySQL unterstützt dies bei der InnoDB-Engine.
Meine Frage ist, wie ich die Zuordnung am besten speichern soll?
Sollte ich in der Produktetabelle eine Spalte anlegen in der sämtliche verfügbaren Märkte kommasepariert gelistet sind?
nein, so etwas ist eine fürchterlich schlechte Idee. Das ist ein Verstoß gegen die erste Normalform, der Dir - wie Du richtig erkennst -
Das dürfte mir Probleme machen wenn ich einen Markt lösche und dann jedes Produkt nach dessen Zuordnung durchsuchen muss um diese ebenfalls zu ändern.
stets Probleme bereiten wird.
Daher habe ich überlegt eine dritte Tabelle anzulegen in der die Zuordnung geregelt wird.
Nur wie muss die Struktur der Tabelle aussehen?
Da die Anzahl der Märkte und Produkte varriert, kann ich beides nicht als Spalte nehmen.
Meine Idee ist jetzt eine Tabelle C mit 2 Spalten.
Eine Spalte mit der ID vom Markt oder des Produkts und eine Spalte wieder mit einer kommaseparierten Liste des Gegenstücks.
Nein, vergiß kommaseparierte Adressen. Einfach eine Spalte mit der ID des Marktes und eine Spalte mit der ID des Produktes. Gegebenenfalls weitere Spalten mit Informationen zur Zuordnung: zum Beispiel die verfügbare Anzahl eines Produktes in einem bestimmten Markt, den Standardpreis des Artikels in diesem Markt - der Preis wird ja nicht überall der gleiche sein, ...
Komplizierter wird es dann noch, wenn ich einen Markt lösche, ein Produkt dadurch ohne Zuordnung dasteht und dashalb ebenfalls gelöscht werden muss.
Nein, ein Produkt wird nicht durch die Schließung von Märkten vom Markt genommen. Es wird deswegen vom Markt genommen, weil es nicht mehr hergestellt wird.
Wie löst man sowas also in der Praxis am besten?
mit einer Zuordnungstabelle. Mit der InnoDB-Engine. Mit Foreign-Key-Constraints, mit ON DELETE CASCADE.
Freundliche Grüße
Vinzenz
Hallo Vinzenz!
ein Produkt kann es bei mehreren Märkten geben,
ein Markt kann mehrere Produkte führen,
=> das ist eine n:m-Beziehung, die Du in MySQL mit einer Beziehungstabelle
umsetzen solltest.
Also war meine Vermutung gar nicht so verkehrt. Nur wie sieht so eine Tabelle aus?
So etwas löst man in Datenbankmanagementsystemen mit Foreign-Key-Constraints und ON DELETE CASCADE. MySQL kann das, aber nicht mit jeder Tabellenengine. MySQL unterstützt dies bei der InnoDB-Engine.
Du hast nicht zufällig 1, 2 Beispiele ausser einem Link auf das Handbuch?
Woher weiß ich welche Engine mein MySQL benutzt? Bis jetzt wusste ich nicht einmal, dass es mehrere gibt ;)
Nein, vergiß kommaseparierte Adressen. Einfach eine Spalte mit der ID des Marktes und eine Spalte mit der ID des Produktes. Gegebenenfalls weitere Spalten mit Informationen zur Zuordnung: zum Beispiel die verfügbare Anzahl eines Produktes in einem bestimmten Markt, den Standardpreis des Artikels in diesem Markt - der Preis wird ja nicht überall der gleiche sein, ...
Der Preis ist in dem Fall nicht relevant.
Also nur eine Tabelle mit den Spalten ID-Markt und ID-Produkt?
Und wenn ein Produkt in mehreren Märkten verfügbar ist, trage ich es mehrmals mit der jeweiligen ID ein?
z.B. (mit den Beispieldaten aus dem OP mit "Tante Emma Laden"...)
+------------+-----------+
| id_product | id_market |
+------------+-----------+
| 1 | 6 |
+------------+-----------+
| 1 | 7 |
+------------+-----------+
Wie muss dann die Struktur der Tabelle aussehen? Index? Spaltentypen?
Oder reicht eine Tabelle mit 2 Integer-Spalten?
»» Komplizierter wird es dann noch, wenn ich einen Markt lösche, ein Produkt dadurch ohne Zuordnung dasteht und dashalb ebenfalls gelöscht werden muss.
Nein, ein Produkt wird nicht durch die Schließung von Märkten vom Markt genommen. Es wird deswegen vom Markt genommen, weil es nicht mehr hergestellt wird.
Ich nehm es nicht vom Markt, ich nehm es nur aus der Liste der den Märkten zuzuordnenen Produkten.
Zusätzlich möchte ich noch eine Spalte in der das Produkt "deaktiviert", also verübergehend aus der Liste genommen werden kann ohne den Eintrag und die Zuordnungen selbst komplett zu löschen. Diese stehen, solange sie "deaktiviert" sind, nicht in der Liste der Artikel die den Märkten zugeordnet sind. Bzw. werden nicht beachtet. Bsp. Saisonartikel.
Diese Angabe müsste also auch noch in die Beziehungstabelle?
Genauso können Märkte verübergehen "gesperrt" werden.
In dem Fall können zwar weiter Produkte zugeordnet werden, aber der Markt soll nicht mehr abgefragt werden können. Also z.B. welche Produkte vorhanden.
Dazu komm ich aber wahrscheinlich erst später.
mit einer Zuordnungstabelle. Mit der InnoDB-Engine. Mit Foreign-Key-Constraints, mit ON DELETE CASCADE.
Mh, ich hoffe das Handbuch ist nicht zu geizig mit der deutschen Übersetzung und Beispielen...
Danke und Grüße, Matze
Hallo
Woher weiß ich welche Engine mein MySQL benutzt? Bis jetzt wusste ich nicht einmal, dass es mehrere gibt ;)
Entweder auf Kommandazeile (mysql) mit
SHOW CREATE TABLE deinetabelle;
oder wenn du PhpMyAdmin hast: Hier gibt es eine DB information_schema.
Hier in die Tabelle "Tables". Hier werden die Storage engines aufgelistet.
z.B. (mit den Beispieldaten aus dem OP mit "Tante Emma Laden"...)
+------------+-----------+
| id_product | id_market |
+------------+-----------+
| 1 | 6 |
+------------+-----------+
| 1 | 7 |
+------------+-----------+Wie muss dann die Struktur der Tabelle aussehen? Index? Spaltentypen?
Oder reicht eine Tabelle mit 2 Integer-Spalten?
Das würde meiner Meinung nach reichen. Du könntest noch zusätzlich eine auto_increment Spalte ID machen die fortlaufend durchnummeriert. ISt aber eigentlich überflüssig.
viele Grüße
hawk
Hallo hawk!
SHOW CREATE TABLE deinetabelle;
Ok danke. Meine Tabellen waren MyISAM.
»» Wie muss dann die Struktur der Tabelle aussehen? Index? Spaltentypen?
»» Oder reicht eine Tabelle mit 2 Integer-Spalten?
Das würde meiner Meinung nach reichen.(...)
Wo bringe ich am besten den Vermerk unter, dass das Produkt oder der Markt vorrübergehend nicht zu Verfügung stehen?
Also nur eine Spalte "active" mit 0 oder 1 als Wert würde ja schon reichen. Häng ich die Spalte direkt an die Tabelle mit den Produkten und Märkten oder an die Tabelle mit den Zuordnungen?
Danke und Grüße, Matze
Hallo,
Wo bringe ich am besten den Vermerk unter, dass das Produkt oder der Markt vorrübergehend nicht zu Verfügung stehen?
Also nur eine Spalte "active" mit 0 oder 1 als Wert würde ja schon reichen. Häng ich die Spalte direkt an die Tabelle mit den Produkten und Märkten oder an die Tabelle mit den Zuordnungen?
wenn ein Markt nicht zur Verfügung steht, ist dies eine Eigenschaft des Marktes.
Wenn ein Produkt allgemein nicht zur Verfügung steht, ist dies eine Eigenschaft des Produktes.
Wenn ein Produkt temporär in einem bestimmten Markt nicht zur Verfügung steht (die Zuordnung soll nicht gelöscht werden), so ist dies eine Eigenschaft der Zuordnung(stabelle).
Freundliche Grüße
Vinzenz
wenn ein Markt nicht zur Verfügung steht, ist dies eine Eigenschaft des Marktes.
Wenn ein Produkt allgemein nicht zur Verfügung steht, ist dies eine Eigenschaft des Produktes.
Wenn ein Produkt temporär in einem bestimmten Markt nicht zur Verfügung steht (die Zuordnung soll nicht gelöscht werden), so ist dies eine Eigenschaft der Zuordnung(stabelle).
Das versteh ich nicht.
Nehmen wir an es gibt einen Aktionsartikel -> Apple IPhone
Der Artikel ist nur für einen bestimmten Zeitraum verfügbar -> nur bei Vertragsabschluss bis 12.12.2xxx
Wenn der Artikel dann nicht mehr zur Verfügung steht, kann ich ihn doch löschen und brauch ihn nicht, mit der Eigenschaft "nicht mehr verfügbar", weiter in meiner Liste speichern?!
Das mit der Eigenschaft der Zuordnung leuchtet mir wieder eher ein.
Danke und Grüße, Matze
Hello,
Nehmen wir an es gibt einen Aktionsartikel -> Apple IPhone
Der Artikel ist nur für einen bestimmten Zeitraum verfügbar -> nur bei Vertragsabschluss bis 12.12.2xxx
Wenn der Artikel dann nicht mehr zur Verfügung steht, kann ich ihn doch löschen und brauch ihn nicht, mit der Eigenschaft "nicht mehr verfügbar", weiter in meiner Liste speichern?!
Und was ist, wenn Du dann für diesen Artikel Gewährleistung leisten musst? (das ist nur ein Beispiel).
Hier sollten die Grundsätze der Buchhaltung gelten und die besagen, dass eine Fehlbuchung nicht durch eine Löschung, sondern durch eine Gegenbuchung aufgehoben werden muss.
Du versaust Dir sonst die Möglichkeit der Historie.
Stell Dir mal vor, Du willst später feststellen, welche Artikel Du von welchen Liferanten wann bezogen hast (das ergibt sicherlich den bedarf für neue Kreuztabellen), und die Beschreibungen sind dann nicht mehr verfügbar, alsomdie Artikel nicht mehr nachvollziehbar.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg

Hallo Tom!
Trotzdem häng ich in der Zwickmühle.
Wenn also eine permanente Nicht-Verfügbarkeit des Marktes/Produktes zu dessen Eigenschaften, also in die jeweilige Tabelle gehört. Und wenn die temporäre Sperrung eines Produktes in die Zuordnungstabelle gehört.
Wo kommt die temporäre Sperre für einen Markt hin?
In der Praxis soll es so ablaufen, dass ich ein Produkt wähle oder eintrage und dabei bestimme für welche Märkte dieses Produkt verfügbar sein soll.
Es werden also in die Tabelle der Art des oberen Beispiels Daten geschrieben:
Produkt mit ID 1 gibts in den Märkten mit den IDs 6 und 7.
Dazu muss ich also vorher die Tabelle mit den Märkten zur Verfügung haben.
Beim Eintragen eines Marktes wird aber nicht automatisch eine Zuordnung vorgenommen.
Es kann also Märkte geben, denen kein einziges Produkt zugeordnet ist.
So einen Markt möchte ich aber auch temporär ausschließen können, so dass ihm auch keine Produkte zugeordnet werden können.
Da er aber noch nicht in der Zuordnungstabelle steht, kann ich da auch nichts ändern. Also ein Feld auf not_available setzen.
Wie mach ich das also?
Und eine andere Frage. Wenn ich die Daten für die Historie brauch, was auch Sinn ergibt, wie lange soll ich die dann speichern? Oder behält man sowas über Jahre hinweg?
Danke und Grüße, Matze
Mahlzeit Matze,
Wenn also eine permanente Nicht-Verfügbarkeit des Marktes/Produktes zu dessen Eigenschaften, also in die jeweilige Tabelle gehört. Und wenn die temporäre Sperrung eines Produktes in die Zuordnungstabelle gehört.
Wo kommt die temporäre Sperre für einen Markt hin?
Falscher Ansatz. Eine Sperre (egal ob temporär oder dauerhaft) eines Marktes ("noch nicht geöffnet", "wird grad renoviert", "geschlossen ab", ...) gehört in die Tabelle aller Märkte (z.B. durch eine Spalte "Aktiv", durch eine Spalte "Aktiv_ab", "Aktiv_bis" o.ä.).
Eine generelle Sperre eines Produkts ("noch nicht verfügbar", "wurde vom Markt genommen") gehört in die Tabelle aller Produkte.
Nur wenn ein bestimmtes Produkt bei einem bestimmten Markt nicht verfügbar ist, sollte diese Sperre in der Zuordnungstabelle vorgenommen werden.
Das ist das, was Vinzenz mit "Eigenschaft des Marktes", "Eigenschaft des Produktes" bzw. "Eigenschaft der Zuordnung(stabelle)" meinte.
Und eine andere Frage. Wenn ich die Daten für die Historie brauch, was auch Sinn ergibt, wie lange soll ich die dann speichern? Oder behält man sowas über Jahre hinweg?
Da ich Deinen bisherigen Beiträgen entnommen habe, dass es sich um eine Art Online-Shop handelt, solltest Du bei der Festlegung der minimalen Speicherdauer aller Daten (im vorliegenden Fall sowohl Markt- und Produktdaten als auch die jeweiligen Zuordnungen) die Grundsätze ordnungsgemäßer Buchführung sowie die daraus abgeleiteten Grundsätze ordnungsmäßiger DV-gestützter Buchführungssysteme beachten. Mit 10 Jahren Aufbewahrungszeit solltest Du AFAIK auf einer relativ sicheren Seite sein - detailliertes Wissen zu diesem Thema hält Dein Steuerberater und/oder Rechtsanwalt vor.
MfG,
EKKi
Hello,
Falscher Ansatz.
Deiner ist aber auch noch nicht zuende gedacht.
Eine generelle Sperre eines Produkts ("noch nicht verfügbar", "wurde vom Markt genommen") gehört in die Tabelle aller Produkte.
Nur wenn ein bestimmtes Produkt bei einem bestimmten Markt nicht verfügbar ist, sollte diese Sperre in der Zuordnungstabelle vorgenommen werden.
Und nun kommt die Praxis. Ein bestimmtes Produkt ist zwar generell nicht mehr nachbestellbar, aber keinesfalls gesperrt (wegen Rückrufes o.ä.). Das bezieht sich auf die übergeordneten Produkt-Meta-Daten.
Nun gibt es noch ca. eine Million von diesen Dingern physisch. Die müssen jetzt dringend in die Märkte umgeleitet werden, in denen die Dinger RENNER waren, um sie noch abverkaufen zu können. Der einzelne Markt kann also von sich aus nicht mehr wirklich nachbestellen, ein gewisses Kontingent an tatsächlich vohandenen Entitäten ist aber noch verfügbar. Dieses wird zugeteilt nach den Absatzchancen, oder auch fremd verklauft an eine Hökerbude.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg

Mahlzeit Tom,
»» Falscher Ansatz.
Deiner ist aber auch noch nicht zuende gedacht.
Habe ich auch nie behauptet. Letztendlich weiß sowieso nur Matze, was genau er (in der Datenbank bzw. der Applikation) abbilden will. Ich wollte lediglich versuchen, ihm das, was er an Vinzenz' Anmerkung nicht verstanden hat, nochmal zu erklären.
»» Eine generelle Sperre eines Produkts ("noch nicht verfügbar", "wurde vom Markt genommen") gehört in die Tabelle aller Produkte.
»»
»» Nur wenn ein bestimmtes Produkt bei einem bestimmten Markt nicht verfügbar ist, sollte diese Sperre in der Zuordnungstabelle vorgenommen werden.Und nun kommt die Praxis. Ein bestimmtes Produkt ist zwar generell nicht mehr nachbestellbar, aber keinesfalls gesperrt (wegen Rückrufes o.ä.). Das bezieht sich auf die übergeordneten Produkt-Meta-Daten.
Dann muss man sich eben eine Eigenschaftsstruktur überlegen, die diese Sonderfälle berücksichtigt. Ich habe nie behauptet, dass ich ein fertiges Datenmodell präsentiert habe - u.a. deshalb schrieb ich ja auch "z.B. durch eine Spalte "Aktiv", durch eine Spalte "Aktiv_ab", "Aktiv_bis" o.ä." ... es kommt darauf an, welche Daten, Eigenschaften und Abhängigkeiten in der Realität auftreten können - davon ausgehend kann man dann ein Datenmodell bauen. Die Realität kennt in diesem Fall aber nur der Fragesteller. Deswegen nahm und nehme ich auch niemals für mich in Anspruch, hier irgendwas Fertiges zu posten.
Also bisschen langsamer schießen, OK?
MfG,
EKKi
Hallo EKKi,
Danke für deine Erklärungen.
Da ich Deinen bisherigen Beiträgen entnommen habe, dass es sich um eine Art Online-Shop handelt(...)
Nö, ganz und gar nicht. Im Prinzip ist es nur zu Übungszwecken damit ich es verstehe. Ich verstehs aber nicht ^^
Also der Grundgedanke war folgende Übung:
Ich nehme beliebige Märkte und ordne denen verschiedene Artikel zu.
Dann trage ich in eine andere Tabelle ein wieviel Produkte X der Markt Y verkauft hat. Daraus will ich mir eine Art Statistik ausgeben lassen.
Bsp:
"Matzes Delikatessen Markt" hat in der 30ten Kalenderwoche 35 Stück "besten Hinterschinken" der Firma "foo" verkauft.
"Matzes Delikatessen Markt" hat in der 30ten Kalenderwoche 17 Stück "Limburger Käse" der Firma "bar" verkauft.
"Ekkis Feinkostladen" hat in der 30ten Kalenderwoche 6 Stück "besten Hinterschinken" der Firma "foo" verkauft.
"Ekkis Feinkostladen" hat in der 30ten Kalenderwoche 14 Stück "Sacher Sahnetorte" der Firma "foobar" verkauft.
Da mir das mit den Märkten und Produkten zu kompliziert wurde,
habe ich noch die Hersteller eingefügt weil es mir einfacher scheint damit umzugehen. Oder auch nicht... :(
Grüße, Matze
Doch noch ein Gedanke dazu.
Wenn ein Produkt temporär in einem bestimmten Markt nicht zur Verfügung steht (die Zuordnung soll nicht gelöscht werden), so ist dies eine Eigenschaft der Zuordnung(stabelle).
Und wenn ein Markt temporär nicht zur Verfügung steht?
Angenommen ich habe einen Markt dem noch keine Produkte zugeordnet sind.
Diesen will ich jetzt sperren.
In der Zuordnungstabelle steht der Markt aber nicht solange ihm keine Artikel zugeordnet sind. Wo soll ich die Sperrung also sonst vornehmen als in der Tabelle mit den Eigenschaften zum Markt?
Ich muss zugeben, ich bin grad einigermaßen verwirrt :(
Danke und Grüße, Matze
Hallo,
» ein Produkt kann es bei mehreren Märkten geben,
» ein Markt kann mehrere Produkte führen,
» => das ist eine n:m-Beziehung, die Du in MySQL mit einer Beziehungstabelle
» umsetzen solltest.Also war meine Vermutung gar nicht so verkehrt. Nur wie sieht so eine Tabelle aus?
Du hast nicht zufällig 1, 2 Beispiele ausser einem Link auf das Handbuch?
Beispiele findest Du zum Beispiel im Artikel Fortgeschrittene Jointechniken in SELFHTML aktuell: Bestellungen_Oktober, Vorteilsclub sind beides solche Beziehungstabellen.
Woher weiß ich welche Engine mein MySQL benutzt? Bis jetzt wusste ich nicht einmal, dass es mehrere gibt ;)
Insbesondere bei Shared Hosting hat man oft keine Auswahl, da gibt's oft nur MyISAM.
Also nur eine Tabelle mit den Spalten ID-Markt und ID-Produkt?
Und wenn ein Produkt in mehreren Märkten verfügbar ist, trage ich es mehrmals mit der jeweiligen ID ein?
Richtig.
z.B. (mit den Beispieldaten aus dem OP mit "Tante Emma Laden"...)
+------------+-----------+
| id_product | id_market |
+------------+-----------+
| 1 | 6 |
+------------+-----------+
| 1 | 7 |
+------------+-----------+
Wie muss dann die Struktur der Tabelle aussehen? Index? Spaltentypen?
Oder reicht eine Tabelle mit 2 Integer-Spalten?
Du solltest für Fremdschlüsselspalten den gleichen Datentyp verwenden, wie in der Tabelle, in der die Spalte Träger des Primärschlüssels ist.
Wenn das gleiche Produkt nur einmal dem gleichen Markt zugeordnet werden kann, so solltest Du auf jeden Fall einen eindeutigen Index für die Spaltenkombination verwenden. Du könntest diesen Index auch als Primärschlüssel verwenden, Du kannst auch eine künstliche Spalte für den Primärschlüssel nehmen.
Freundliche Grüße
Vinzenz
Hallo Vinzenz!
Danke erstmal für die Links!
Insbesondere bei Shared Hosting hat man oft keine Auswahl, da gibt's oft nur MyISAM.
ALTER TABLE tbl ENGINE=InnoDB hat zumindest funktioniert und ich kann weiter auf die Tabellen zugreifen wie gewohnt.
Ich merke keinen Unterschied. Somit sollten die Tabellen jetzt über InnoDB laufen oder?
»» Wie muss dann die Struktur der Tabelle aussehen? Index? Spaltentypen?
»» Oder reicht eine Tabelle mit 2 Integer-Spalten?
Du solltest für Fremdschlüsselspalten den gleichen Datentyp verwenden, wie in der Tabelle, in der die Spalte Träger des Primärschlüssels ist.
In den Tabellen A und B ist die Spalte
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
Also 2 Integer Spalten?!
Wenn das gleiche Produkt nur einmal dem gleichen Markt zugeordnet werden kann (..)
Daran hab ich noch gar nicht gedacht, aber genau so soll es sein.
Wäre ja blödsinn wenn ich sage "da gibts Milch und Milch" wenn es sich um das gleiche Produkt handelt.
(..) so solltest Du auf jeden Fall einen eindeutigen Index für die Spaltenkombination verwenden. Du könntest diesen Index auch als Primärschlüssel verwenden, Du kannst auch eine künstliche Spalte für den Primärschlüssel nehmen.
Mh, das versteh ich nicht ganz. Eine der Spalten als index nehmen? Oder doch zusätzlich eine Spalte AUTO_INCREMENT PRIMARY KEY anlegen?
Danke und Grüße, Matze
Hallo,
In den Tabellen A und B ist die Spalte
id INT NOT NULL AUTO_INCREMENT PRIMARY KEYAlso 2 Integer Spalten?!
» Wenn das gleiche Produkt nur einmal dem gleichen Markt zugeordnet werden kann (..)
Daran hab ich noch gar nicht gedacht, aber genau so soll es sein.
Wäre ja blödsinn wenn ich sage "da gibts Milch und Milch" wenn es sich um das gleiche Produkt handelt.
eben, das ist eine spezielle Anforderung von Dir. Davon kannst Du nicht auf den Allgemeinfall schließen. Ich kann mir sinnvolle Fälle für Zuordnungen vorstellen, bei denen so etwas erlaubt sein muss.
» (..) so solltest Du auf jeden Fall einen eindeutigen Index für die Spaltenkombination verwenden. Du könntest diesen Index auch als Primärschlüssel verwenden, Du kannst auch eine künstliche Spalte für den Primärschlüssel nehmen.
Mh, das versteh ich nicht ganz. Eine der Spalten als index nehmen?
Nein, einen eindeutigen Index über die Kombination der beiden Fremdschlüsselspalten, gern auch als Primärschlüssel.
Freundliche Grüße
Vinzenz
Hallo Vinzenz!
Danke nochmals!
»» Mh, das versteh ich nicht ganz. Eine der Spalten als index nehmen?
Nein, einen eindeutigen Index über die Kombination der beiden Fremdschlüsselspalten, gern auch als Primärschlüssel.
Was ist das und wie geht das?
Danke und Grüße, Matze
Hallo,
» »» Mh, das versteh ich nicht ganz. Eine der Spalten als index nehmen?
» Nein, einen eindeutigen Index über die Kombination der beiden Fremdschlüsselspalten, gern auch als Primärschlüssel.
Was ist das und wie geht das?
Ein eindeutiger Index, der sich auf die Kombination zweier Spalten bezieht. Das heißt, in jeder Spalte kann jeder Wert durchaus mehrfach vorkommen, jede Kombination jedoch maximal einmal.
Und hier ein kleines Beispiel:
-- Tabelle maerkte
CREATE TABLE maerkte (
id_markt INTEGER unsigned NOT NULL AUTO_INCREMENT,
markt VARCHAR(45) NOT NULL,
PRIMARY KEY (id_markt) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Tabelle produkte
CREATE TABLE produkte (
id_produkt INTEGER unsigned NOT NULL AUTO_INCREMENT,
bezeichnung VARCHAR(45) NOT NULL,
PRIMARY KEY (id_produkt) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Beziehungstabelle produkte_zu_maerkte
CREATE TABLE produkte_zu_maerkte (
id_markt INTEGER unsigned NOT NULL, -- beachte: gleicher Datentyp
-- wie in Tabelle maerkte
id_produkt INTEGER unsigned NOT NULL, -- gleiches hier wie in
-- Tabelle produkte
PRIMARY KEY (id_markt, id_produkt), -- unser Zweispalten-Index, hier als
-- Primärschlüssel
-- der erste Fremdschlüssel schränkt die Spalte id_produkt ein
KEY FK_produkte (id_produkt),
CONSTRAINT FK_produkte FOREIGN KEY (id_produkt)
REFERENCES produkte (id_produkt) -- bezieht sich auf die Spalte
-- id_produkt der Tabelle produkte
ON DELETE CASCADE -- mit Löschweitergabe und
ON UPDATE CASCADE, -- Updateweitergabe
-- analog der zweite Fremdschlüssel, der die Beziehung zur Tabelle
-- maerkte herstellt. Gleiche Spaltennamen sind übrigens nicht erforderlich.
CONSTRAINT FK_maerkte FOREIGN KEY (id_markt)
REFERENCES maerkte (id_markt)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Fügen wir nun ein paar Datensätze ein:
INSERT INTO maerkte (id_markt, markt) VALUES
(1, 'Matzes Delikatessen'),
(2, 'Feinkost Schmieder');
führt zu folgender Tabelle maerkte
id_markt | markt
---------+------------------------
1 | Matzes Delikatessen
2 | Feinkost Schmieder
und
INSERT INTO produkte (id_produkt, bezeichnung) VALUES
(1, 'Milch'),
(2, 'Honig'),
(3, 'Sonnencreme'),
(4, 'Wintermantel');
produkte
id_produkt | bezeichnung
-----------+--------------
1 | Milch
2 | Honig
3 | Nektar
4 | Ambrosia
Jetzt können wir die Märkte mit Produkten füllen:
Matzes Delikatessen führt Milch und Honig
INSERT INTO produkte_zu_maerkte (id_markt, id_produkt) VALUES
(1, 1),
(1, 2);
-- wird erfolgreich ausgeführt
Toms Feinkostladen fängt mit Nektar und Ambrosia an:
INSERT INTO produkte_zu_maerkte (id_markt, id_produkt) VALUES
(2, 3),
(2, 4);
-- wird erfolgreich ausgeführt
Tom nimmt Milch ins Programm:
Toms Feinkostladen fängt mit Nektar und Ambrosia an:
INSERT INTO produkte_zu_maerkte (id_markt, id_produkt) VALUES
(2, 1);
-- wird erfolgreich ausgeführt, diese Kombination gibt es noch nicht
Schauen wir uns die Zuordnungstabelle an:
id_markt | id_produkt
---------+-----------
1 | 1
1 | 2
2 | 3
2 | 4
2 | 1
Wir versuchen, die Milch erneut Matzes Delikatessenladen anzudrehen:
INSERT INTO produkte_zu_maerkte (id_markt, id_produkt) VALUES
(1, 1);
-- führt zu folgender Fehlermeldung
-- Fehlernummer 1062, Duplicate entry '1-1' for key 'PRIMARY'
Milch soll nun die ID 5 bekommen:
UPDATE
produkte
SET
id_produkt = 5
WHERE
bezeichnung = 'Milch'
Schauen wir uns nun die Beziehungstabelle an:
SELECT
id_markt,
id_produkt
FROM
produkte_zu_maerkte
Ergebnis:
id_markt | id_produkt
---------+-----------
1 | 5
1 | 2
2 | 3
2 | 4
2 | 5
Wir sehen: ON UPDATE CASCADE sorgt dafür, dass in der Beziehungstabelle die id der Milch ebenfalls aktualisiert wird.
Nektar wird von der Produktliste gestrichen:
DELETE FROM
produkte
WHERE
bezeichnung = 'Nektar'
Schauen wir uns erneut die Beziehungstabelle an:
Ergebnis:
id_markt | id_produkt
---------+-----------
1 | 5
1 | 2
2 | 4
2 | 5
Die Zuordnung von Nektar zu Feinkost Schmieder ist ebenfalls gelöscht worden - wegen ON DELETE CASCADE
Versuchen wir einen Artikel mit der id_produkt 7 (zu der es keinen Datensatz in der Tabelle produkte gibt) zu Matzes Laden hinzuzufügen:
INSERT INTO
produkte_zu_maerkte (id_markt, id_produkt)
VALUES
(1, 7)
Dieses Statement schlägt fehl:
Fehlernummer 1452,
Cannot add or update a child row: a foreign key constraint fails ...
Ich hoffe, Du verstehst jetzt wie man FOREIGN-KEY-Constraints erstellen kann, und welchen Nutzen Du daraus ziehen kannst. Du solltest außerdem nachvollziehen können, wie man Mehrspaltenindexe erstellt und wie sie arbeiten. Eine Anmerkung noch: Es gibt auch nicht eindeutige Mehrspaltenindexe.
Freundliche Grüße
Vinzenz
Hallo Vinzenz!
Wow, das ist doch ganz schön viel.
Herzlichen dank, damit kann ich mich erstmal eine Weile beschäftigen.
Grüße, Matze
Hallo nochmal,
Ich hoffe, Du verstehst jetzt wie man FOREIGN-KEY-Constraints erstellen kann, und welchen Nutzen Du daraus ziehen kannst.
nach ewigem rumprobieren dann doch nicht. Ich kann es nichtmal übersetzen
Alle deine CREATE-Statements bringen mir:
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8' at line 4"
Ich hab dann mal versucht aus BTREE schlau zu werden bzw zu verstehen was das überhaupt ist. Hat auch nicht viel gebracht :(
Du solltest außerdem nachvollziehen können, wie man Mehrspaltenindexe erstellt und wie sie arbeiten.
Kann ich leider nicht weil ich deine Beispiele nicht funktionieren, also konnte ich auch nicht damit "spielen" und "testen" :(
Du hast in deinem Code
-- der erste Fremdschlüssel schränkt die Spalte id_produkt ein
KEY FK_produkte (id_produkt),
CONSTRAINT FK_produkte FOREIGN KEY (id_produkt)
und
-- analog der zweite Fremdschlüssel, der die Beziehung zur Tabelle
-- maerkte herstellt. Gleiche Spaltennamen sind übrigens nicht erforderlich.
CONSTRAINT FK_maerkte FOREIGN KEY (id_markt)
Wieso ist beim zweiten Teil kein KEY FK_maerkte (id_markt) vor CONSTRAINT...
Ist das so richtig? Mh und ich versteh auch gar nicht wie ich es angehen müsste wenn ich etwas anderes ausser die ids ändern will. Die tauchen in den Beispielen verwirrend oft auf :(
Das mit den Märkten und Produkten scheint mir zu kompliziert.
Ich versuch grad eine einfacherer Hersteller-Produkt-Beziehung.
Da ist die Abhängigkeit nur in eine Richtung.
Also wenn ich eine Spalte bei den Herstellern ändere, soll sich auch eine Spalte bei den Produkten ändern. Z.B. "Verfügbarkeit". Ist ein Hersteller nicht verfügbar sollen es die zugehörigen Produkte auch nicht sein. Das krieg ich aber auch nicht hin :(
Grüße, Matze
Oh man, ausgerechnet jetzt hab ich den Fehler gefunden.
Es muss heißen PRIMARY KEY USING BTREE (id_produkte) nicht PRIMARY KEY (id_produkte) USING BTREE.
Jetzt kann ich anfangen einfache Hersteller- und Produkte-Tabellen anzulegen. Dazu eine Tabelle mit der Zuordnung und dann kann ich damit experimentieren.
Grüße, Matze
Hallo
Sollte ich in der Produktetabelle eine Spalte anlegen in der sämtliche verfügbaren Märkte kommasepariert gelistet sind?
Das wäre vermutlich die denkbar schlechteste Lösung.
Warum machst du nicht einfach in der Produkt Tabell eine zusätzliche Spalte mit "MarktID" wo du dann beim Eintragen eines neuen Produkts die entsprechende MArkt ID einfügst.
So bekommst du die Zuordnung
Daher habe ich überlegt eine dritte Tabelle anzulegen in der die Zuordnung geregelt wird.
Nur wie muss die Struktur der Tabelle aussehen?
viele Grüße
hawk
Warum machst du nicht einfach in der Produkt Tabell eine zusätzliche Spalte mit "MarktID" wo du dann beim Eintragen eines neuen Produkts die entsprechende MArkt ID einfügst.
So bekommst du die Zuordnung
Nein, wie Vinzenz sagte:
ein Produkt kann es bei mehreren Märkten geben,
ein Markt kann mehrere Produkte führen,
Es geht also 'über kreuz'. Sonst wär es ja so schön einfach ;)
Grüße, Matze
Hi,
die Stichworte n:m, Kreuztabelle und ON DELETE CASCADE hast Du ja schon bekommen. Darum nur noch eine Kleinigkeit:
Sollte ich in der Produktetabelle eine Spalte anlegen in der sämtliche verfügbaren Märkte kommasepariert gelistet sind?
Wenn Du in einer Zelle den(!) Wert "1,3,7,8" gespeichert hast und dieser Wert aussagt, welche Beziehung zur Märkte-Tabelle besteht, dann bedeutet dies, dass der Datensatz mit dem(!) Märkte-Datensatz "1,3,7,8" verknüpft ist. Die Inhalte einer Tabellenzelle sind atomar - also unteilbar. Versuche nicht, sie zu teilen, das führt nur zu Problemen der Größenordnung Hiroshima.
Cheatah