Zwei Spalten Primary Key -> Vermeiden?


  • Administrator

    @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 kenne 🙂

    Hauptsä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) ORT

    TB3

    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 😃


  • Administrator

    Unix-Tom schrieb:

    Mehrere PK sind auch nicht notwendig

    Wozu?

    TB1

    ID(PK) Name

    TB2
    ID(PK) ORT

    TB3

    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)


  • Administrator

    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.


  • Administrator

    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 hellsehen 😉

    Schon 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



  • Der Grund warum Frameworks das nicht unterstützen könnte einfach sein dass das Framework sonst komplizierter würde.

    Ist halt einfacher wenn ich jedes "Objekt" (jede Zeile in einer DB) grundsätzlich immer über einen 32 oder 64 Bit Integer identifizieren kann (+Tabellenname natürlich, der aber meist implizit ist). Wenn man das im Framework quasi festlegt vereinfachen sich wohl einige Fälle die sonst etwas aufwändiger wären.

    z.B. könnte man eine "Table" Klasse machen die eine Funktion "GetRow(int64_t rowID)" hat. Ob die RowID wirklich 64 Bit ist ist dabei egal, nur *muss* dafür die ID "einspaltig" sein. Theoretisch könnte man sogar Strings als ID erlauben wenn man statt eines int64_t einen Variant übergibt.

    ----

    Ich habe "mittel bis viel" Erfahrung mit Datenbanken, und zu dem Fall "Link-Table" kann ich aus eben dieser Erfahrung sagen: ich wüsste keinen Fall wo ein zusätzlicher Primary-Key sinn machen würde.

    Wenn überhaupt, dann macht ein extra Primary-Key nur dann sinn well
    a) alle anderen Candidate-Keys zu breit oder aus einem anderen Grund ungeeignet wären und
    b) die Tabelle überhaupt von anderen Tabellen aus referenziert wird.

    Bei einer klassichen Link-Tabelle ist meist a) schon nicht gegeben (2x 32 Bit ist IMO noch nicht wirklich "zu breit") und b) schon überhaupt nicht.

    ----

    Mein Hauptproblem am ganzen ist eigentlich, dass ich kaum praktische Erfahrung habe mit den Datenbanken.

    Dann würde ich dir wirklich empfehlen dir den (gratis) SQL Server 2005 Express und das dazupassende Management Studio runterzuladen und dich damit etwas zu spielen. SQL Server 2005 Express ist auch kein "Kinderspielzeug", das ist im Prinzip der vollständige SQL Server, bloss mit einem Limit auf die max. Datenbank-Grösse und einigen fehlenden Features die du für diverse Experimente nicht brauchen wirst (Clustering, ...).


Anmelden zum Antworten