Zwei Spalten Primary Key -> Vermeiden?
-
Hallo zusammen,
Ich habe jetzt schon mehrere Mal gehört, dass man Primary Keys über zwei Spalten vermeiden sollte. Nur ist es mir bis heute ein Rätsel, wieso man dies eigentlich vermeiden sollte. Gerade bei der Verbindung von zwei oder mehr Primary Keys in einer eigenen Tabelle, finde ich es äusserst praktisch, wenn man nicht einen zusätzlichen unnötigen Schlüssel macht.
Als Beispiel:
Tabelle 1: |key| ... | A | ... |---|---- | | Tabelle 2: |key| | B | ... |---|---- | |
Und nun würde ich gerne Verknüpfungen machen, da würde ich das hier tun:
|key|key| | A | B | |---|---| | | |
Empfohlen wird allerdings immer das folgende zu tun:
|key| | C | A | B | |---|---|---| | | | |
Und C als eine automatisch inkrementierbare ID. Aber das ist doch völlig unnötig? Verschwendet Speicherplatz und limitiert die Menge der Verknüpfungen und somit auch der Einträge in Tabelle 1 und 2.
Ich wäre froh, wenn mich da mal jemand aufklären könnte, wo der Sinn dahinter liegt.
Grüssli
-
Zuerst muss mal gesagt werden das ein RDBMS eine Zeile eindeutig identifizieren können muss.
Dh.: Es dürfen in der Tabelle keine 2 gleichen Datensätze sein.
Deshalb verwendet man dann einen AutoInc.
1 Hallo Welt
2 Hallo Weltist möglich.
Hallo Welt
Hallo Weltist möglich aber darf nicht sein.
Wenn man einen Datensatz löschen möchte dann ist es oben möglich unten aber nicht.Es gibt Grundsätzlich keine Regeln wie man einen PK setzt.
Es kommt immer auf die Daten der Tabellen an.
Hilfreich ist es Tabellen zu Normalisieren.
Normalisierung findest du bei div. Suchmaschinen.
-
Unix-Tom schrieb:
...
Wenn man einen Datensatz löschen möchte dann ist es oben möglich unten aber nicht...Viel besser: Unter manchen Systemen wird die komplette Tabelle gelöscht, wenn es keinen PK gibt. Zumindest unter ADO und ODBC, wo der Treiber sich sein DELETE Statement zusammenbaut und dann keine Identifizierungs-Bedingung anhängen kann
Ich habs mir mit der Zeit angewöhnt jeder Tabelle eine ID Spalte zu geben. Es vereinfacht das Ganze auch sehr und lässt weitere Möglichkeiten im Datenmodell offen. Was z.B. wenn eine der vorgesehenen Key-Spalten NULL sein kann? Mit einem Unique Index ist das möglich, mit einem Primary Key nicht.
-
Die meisten DBs kommen super mit doppelten Zeilen klar, weiss nicht was hier schonwieder geschreiben wird.
Es stimmt dass es oft zu Problemen kommt wenn irgendwo doppelte Zeilen drinstehen, aber das Statement ...Zuerst muss mal gesagt werden das ein RDBMS eine Zeile eindeutig identifizieren können muss.
Dh.: Es dürfen in der Tabelle keine 2 gleichen Datensätze sein....ist mir einfach zu absolut.
Ist hier aber irrelevant.
Bei klassischen Link-Tabellen (2 FK Spalten und sonst nix) verwende ich meist einen PK der einfach aus den beiden verlinkten FKs zusammengesetzt ist. Also keine extra Spalte.
Ausnahme ist wenn ich die Zeilen in dieser Link-Tabelle selbst irgendwo referenzieren muss, was dann aber meist bedeutet dass es keine einfachen "2 FK" Linktabellen mehr sind, sondern noch irgendwas dazukommt (Sequenz-Nummber, ...).Von der Theorie her gibt es IIRC aber keine "Vorschrift" dass ein PK nur aus einer Spalte zu bestehen hat. (Falls eine der Normalformen das verlangt bitte mich zu korrigieren)
-
@Unix-Tom,
Das ein PK immer eindeutig sein muss und normalerweise auch jede Tabelle einen PK hat, ist mir schon klar.
Es ging mir wirklich nur um mehrspaltige PKs, da ich immer wieder davon lese, dass man sie vermeiden solle.@hustbaer,
Es ging mir wirklich nur um klassiche Verknüpfungstabellen oder halt Linktabellen. Arbeite zu wenig mit Datenbanken zusammen, als das ich all die Begriffe kenneHauptsächlich gelesen habe ich dies bei Frameworks für das Arbeiten mit Datenbanksystemen. In vielen Frameworks, welche ich angeschaut habe, werden Tabellen mit mehrspaltigen PKs nicht unterstützt. Teilweise steht sogar ganz klar, dass man sie in Zukunft auch nicht unterstützen möchte, da man solche PKs vermeiden solle. Es steht aber nie warum ... und es ist mir eben ein völliges Rätsel.
In der Datenbankvorlesung, welche ich mal hatte, kam davon auch nichts vor und im Buch, welches ich zu Datenbanken habe, steht davon auch nichts drin. Daher wollte ich mal einfach nachfragen, aber wenn ihr es auch nicht wisst ...
Such ich mir vielleicht mal ein Framework, welches dies unterstützt oder unterwerfe mich halt der unlogischen Logik der Frameworkentwickler.Grüssli
-
Mehrere PK sind auch nicht notwendig
Wozu?
TB1
ID(PK) Name
TB2
ID(PK) ORTTB3
ID(PK) PKTB1 PKTB2
INDEX auf PKTB1 PKTB2
Somit bekommt man Name und Ort einer Personal und hat normalisiert
-
hustbaer schrieb:
Die meisten DBs kommen super mit doppelten Zeilen klar, weiss nicht was hier schonwieder geschreiben wird.
Es stimmt dass es oft zu Problemen kommt wenn irgendwo doppelte Zeilen drinstehen, aber das Statement ...Zuerst muss mal gesagt werden das ein RDBMS eine Zeile eindeutig identifizieren können muss.
Dh.: Es dürfen in der Tabelle keine 2 gleichen Datensätze sein....ist mir einfach zu absolut.
Ist hier aber irrelevant.
In einem RDBMS MUSS jeder Datensatz eindeutig sein.
Da ist nichts mit Absolut etc.
Dies sind die Vorgaben eines RDBMS.
-
@Unix-Tom:
OK. Streichen wir das R aus RDBMS.Was ich damit sagen wollte: es gibt RDBMS' die man als einfaches DBMS einsetzen kann, die mit "gleichen Zeilen" einigermassen klarkommen.
MS-SQL Server hat z.B. kein echtes Problem damit. Klar, man kann das Management Studio nichtmehr gescheit verwenden um Tabellen mit solchen Einträgen zu editieren, aber gehen tut es. Einzelne Zeilen löschen kann man z.B. mit "DELETE [tablename] WHERE CURRENT OF [cursorname]". Wenn ich in eine Tabelle 10 gleiche Einträge mache, dann 3 davon mit "WHERE CURRENT OF" lösche, dann sind danach noch 7 Einträge da, genau was man erwarten würde.
Ich glaube nicht dass es Fälle gibt wo es Sinn macht sowas zu machen (und wo es dann vor allem gute Gründe gibt nicht eine numerische Spalte mit Auto-Wert als PK dazuzumachen). Ich meine nur grundsätzlich geht es.
-
hustbaer schrieb:
...
MS-SQL Server hat z.B. kein echtes Problem damit. Klar, man kann das Management Studio nichtmehr gescheit verwenden um Tabellen mit solchen Einträgen zu editieren, aber gehen tut es. Einzelne Zeilen löschen kann man z.B. mit "DELETE [tablename] WHERE CURRENT OF [cursorname]". Wenn ich in eine Tabelle 10 gleiche Einträge mache, dann 3 davon mit "WHERE CURRENT OF" lösche, dann sind danach noch 7 Einträge da, genau was man erwarten würde...lol! Ich weiss grad nicht, ob du das wirklich ernst meinst Ich würde keiner Anwendung über den Weg trauen die auf diesen Daten arbeitet und wenn ich sowas entwickeln würde, würde mein Chef mich auf der Stelle mit Arschtritt rausfeuern
-
Unix-Tom schrieb:
Mehrere PK sind auch nicht notwendig
Wozu?
TB1
ID(PK) Name
TB2
ID(PK) ORTTB3
ID(PK) PKTB1 PKTB2
INDEX auf PKTB1 PKTB2
Somit bekommt man Name und Ort einer Personal und hat normalisiert
Aber du hast doch eine unnötige ID in TB3. Schliesslich könnte man gleich PKTB1 mit PKTB2 als PK von TB3 nehmen. Wieso also eine zusätzliche ID? Was ist der Zweck?
Grüssli
-
Cpp_Junky schrieb:
hustbaer schrieb:
...
MS-SQL Server hat z.B. kein echtes Problem damit. Klar, man kann das Management Studio nichtmehr gescheit verwenden um Tabellen mit solchen Einträgen zu editieren, aber gehen tut es. Einzelne Zeilen löschen kann man z.B. mit "DELETE [tablename] WHERE CURRENT OF [cursorname]". Wenn ich in eine Tabelle 10 gleiche Einträge mache, dann 3 davon mit "WHERE CURRENT OF" lösche, dann sind danach noch 7 Einträge da, genau was man erwarten würde...lol! Ich weiss grad nicht, ob du das wirklich ernst meinst Ich würde keiner Anwendung über den Weg trauen die auf diesen Daten arbeitet und wenn ich sowas entwickeln würde, würde mein Chef mich auf der Stelle mit Arschtritt rausfeuern
Wo habe ich denn geschrieben dass ich sowas machen würde?
Es wurde geschrieben "es geht nicht" (sinngemäss), und nicht "sowas macht man nicht". Und es geht eben doch. Was damit ob man es machen sollte wieder garnix zu tun hat.Ein Unterschied der dir offensichtlich nicht eingeht. Kann ich aber nix dafür.
-
Dravere schrieb:
Aber du hast doch eine unnoetige ID in TB3. Schliesslich koennte man gleich PKTB1 mit PKTB2 als PK von TB3 nehmen. Wieso also eine zusaetzliche ID? Was ist der Zweck?
ich erinner mich gehoert zu haben das ein PK auf nur eine Spalte fuer das DBMS leichter zu verwalten sei. Keine Ahnung, was dran ist.
Auf alle Faelle kann man so den Eintrag selbst wieder in einer anderen Tabelle referenzieren
-
hustbaer schrieb:
Cpp_Junky schrieb:
hustbaer schrieb:
...
MS-SQL Server hat z.B. kein echtes Problem damit. Klar, man kann das Management Studio nichtmehr gescheit verwenden um Tabellen mit solchen Einträgen zu editieren, aber gehen tut es. Einzelne Zeilen löschen kann man z.B. mit "DELETE [tablename] WHERE CURRENT OF [cursorname]". Wenn ich in eine Tabelle 10 gleiche Einträge mache, dann 3 davon mit "WHERE CURRENT OF" lösche, dann sind danach noch 7 Einträge da, genau was man erwarten würde...lol! Ich weiss grad nicht, ob du das wirklich ernst meinst Ich würde keiner Anwendung über den Weg trauen die auf diesen Daten arbeitet und wenn ich sowas entwickeln würde, würde mein Chef mich auf der Stelle mit Arschtritt rausfeuern
Wo habe ich denn geschrieben dass ich sowas machen würde?
Es wurde geschrieben "es geht nicht" (sinngemäss), und nicht "sowas macht man nicht". Und es geht eben doch. Was damit ob man es machen sollte wieder garnix zu tun hat.Ein Unterschied der dir offensichtlich nicht eingeht. Kann ich aber nix dafür.
Hier soll nur nicht der Eindruck entstehen, das sowas "irgendwie geht". Das ist ganz grosser Bullshit, sonst nichts.
-
Es gehen viele Sachen die ganz grosser Bullshit sind.
Man kann in C++ Programme mit nur "if" und "goto" als flow-control schreiben. Das geht. Zu behaupten es ginge nicht wäre einfach falsch. Grosser Bullshit ist es trotzdem.Und?
Darf deswegen jetzt nirgends mehr darauf hingewiesen werden dass es geht? Sollen wir jetzt den Standard umschreiben?
-
OK, eingen wir uns darauf: Man darf es nicht machen weil ein RDBMS nicht dafür ausgelegt ist und ein RDBMS jeden Datensatz eindeutig identifizieren können sollte.
-
Dravere schrieb:
Aber du hast doch eine unnötige ID in TB3. Schliesslich könnte man gleich PKTB1 mit PKTB2 als PK von TB3 nehmen. Wieso also eine zusätzliche ID? Was ist der Zweck?
Grüssli
Du hast Recht aber es soll ja auch ein Lerneffekt sein.
Wenn man mit RDBMS arbeitet sollte man sich zwangsweise mit DB-Design und Normalisierung rumschlagen.
Es gibt keine Allgemein gültige Aussage. Es hängt immer von den Daten ab.
-
Unix-Tom schrieb:
OK, eingen wir uns darauf: Man darf es nicht machen weil ein RDBMS nicht dafür ausgelegt ist und ein RDBMS jeden Datensatz eindeutig identifizieren können sollte.
Damit kann ich leben
@OP: lies dir den Artikel zu den Normalformen auf Wikipedia durch, ich fand den ganz gut:
http://de.wikipedia.org/wiki/Normalisierung_(Datenbank)
-
Will jetzt trotzdem noch darauf antworten, obwohl ich mich ehrlich gesagt ein wenig geärgert habe. Ich weiss was die Normalisierung ist, wir haben das durchgekaut bis ich satt davon hatte. Und ich habe auch nie gefragt, was es mit der Normalisierung auf sich hat. Ich habe nie von Tabellen erzählt, wo es mehr Daten drin hat, als zwei Fremdschlüssel. Ich habe nur gefragt, wieso man darauf verzichten sollte, in einer Tabelle, wo nur zwei Fremschlüssel sind, diese beiden Fremdschlüssel nicht gleich als Primärschlüssel zu verwenden. Weil ich immer wieder gelesen habe, dass man besser eine dritte Spalte erstellt, mit einem Primärschlüssel, welcher nichts mit sonst irgendetwas zu tun hat.
Daher vielleicht nochmals eine konrete Fragen:
Was ist mit der Aussage von zwutz, was ist daran wahr?zwutz schrieb:
ich erinner mich gehoert zu haben das ein PK auf nur eine Spalte fuer das DBMS leichter zu verwalten sei. Keine Ahnung, was dran ist.
Und vielleicht noch eine an Unix-Tom:
Unix-Tom schrieb:
Du hast Recht aber es soll ja auch ein Lerneffekt sein.
Wenn man mit RDBMS arbeitet sollte man sich zwangsweise mit DB-Design und Normalisierung rumschlagen.
Es gibt keine Allgemein gültige Aussage. Es hängt immer von den Daten ab.Was für einen Lerneffekt??? Die ID ist unnötig. Und ich habe mich mit DB-Design und Normalisierung rumgeschlagen, wie kommst du überhaupt drauf, dass ich das nicht hätte? Und ich habe ganz klar gesagt, was für Daten in der Tabelle sind. Es ist eine reine Verknüpfung, keine zusätzlichen Daten. Nur zwei Fremdschlüssel, das ist alles.
Grüssli
-
@Dravere:
Sorry, ich wollte dich nicht ärgern, ich hatte einfach den Eindruck dass dir das nicht 100% klar ist - ich kann auch nicht hellsehen----
Dravere schrieb:
Daher vielleicht nochmals eine konrete Fragen:
Was ist mit der Aussage von zwutz, was ist daran wahr?zwutz schrieb:
ich erinner mich gehoert zu haben das ein PK auf nur eine Spalte fuer das DBMS leichter zu verwalten sei. Keine Ahnung, was dran ist.
Das kann man so nicht sagen. Kürzere Keys sind i.A. besser als längere Keys. Wenn sonst alles gleich bleibt ist als ein Key der aus einem "int" besteht einem Key der aus 2 "int" besteht vorzuziehen.
Allerdings bleibt meist nicht "sonst alles gleich". Was effizient ist kommt letztlich auf die Abfragen an die man auf die Daten macht.
In vielen Fällen wird es durchaus Sinn machen zusätzlich zu einem recht langen Candiate-Key einen einspaltigen Primary-Key zu machen, in anderen Fällen könnte es sogar die Performance verschlechtern.Wenn man halbwegs ein Verständnis dafür hat wie ein RDBMS intern arbeitet ist es (in den meisten Fällen) halbwegs logisch was schnell sein wird und was nicht.
SQL Server (Express) bzw. das SQL Server Management Studio hat ein nettes Feature, das kann dir nämlich den "execution plan" anzeigen der für eine Abfrage verwendet wird, und welche Knoten (Operatoren) wieviel Zeit (aufgeschlüsselt in CPU + IO) verbraucht haben. Mir hat das sehr geholfen gewisse Dinge zu verstehen, ein intuitives Gefühl dafür zu bekommen was langsam sein wird und was nicht etc.
-
hustbaer schrieb:
@Dravere:
Sorry, ich wollte dich nicht ärgern, ich hatte einfach den Eindruck dass dir das nicht 100% klar ist - ich kann auch nicht hellsehenSchon gut, bin nur etwas aus der Haut gefahren. Unix-Tom hat das mit der Normalisierung gebracht, nur habe ich nie danach oder in diese Richtung gefragt. Und während man mir so einen Link zuwirft, welcher nichts mit meinem Problem zu tun hat, diskutieren andere über etwas ganz anderes in "meinem" Thread. Das empfinde ich schon irgendwie als ein wenig respektlos, nicht?
Mein Hauptproblem am ganzen ist eigentlich, dass ich kaum praktische Erfahrung habe mit den Datenbanken. Ich verstehe in der Theorie so ziemlich vieles, was um und in der Datenbank abgeht, aber angewendet hate ich es bisher kaum.
Deshalb dachte, könnte mir jemand mit Erfahrung weiterhelfen, wieso man eben solche doppelspaltigen Schlüssel meiden sollten, zum Beispiel bei einfachen Verknüpfungen (also Tabelle mit nur zwei Fremdschlüssel).
Aber bisher kam noch keine Empfehlung, dass man sowas vermeiden sollte, daher frag ich mich nun wiederrum, wieso gewisse Frameworks dies nicht unterstützen wollen. Muss ich halt dort mal nachfragen gehen, anscheinend ist das nicht so offensichtlich, nicht mal für jemand mit Erfahrung. Dann lag es nicht einfach daran, dass mir dies wegen mangelnder Erfahrung nicht klar wurde.Grüssli