SQL Redundanz und Änderungen bei kombinierten Primärschlüsseln.

T

Tersus

Gast
Guten morgen,

Code:
|------+------+------+---------------------|
| PK_A | PK_B | PK_C | non_PK              |
|------+------+------+---------------------|
| "A"  | "B"  | "C"  | "wert"              |
| "A"  | "B"  | "D"  | "Andererwert"       |
| "A"  | "B"  | "D"  | "WiederAndererWert" |
|------+------+------+---------------------|

Ich habe eine Tabelle mit 3 Primärschlüssel. Diese Schlüssel haben untereinander absolut keine funktionale Abhängigkeit. Jeder Schlüssel steht wirklich für sich, ohne Beziehung zu den jeweils zwei anderen. Und nur durch alle drei gemeinsam kommt eine Eindeutigkeit zustande.

Nun ergibt sich folgendes Problem: Die Primärschlüssel sind Zeichenketten! Schlimmer noch: Es könnte passieren, dass sich der Name eines PKs ändert. Im Beispiel oben kann es passieren, dass "A" irgendwann mal in "B" umbenannt werden muss.

Meine Fragen:
  1. Ist das bedenklich?
  2. Sollte ich wirklich für jeden dieser natürlichen PKs einen künstlichen Integer PKs anlegen?
  3. Muss ich sogar alle natürlichen PKs in extra Tabellen auslagern?
Ich habe ja irgendwie gehofft, dass das dbms für natürliche PKs selbst einen internen PK anlegt.
 
Warum sind das PK bzw warum müssen das PK sein?

Mach einen eigenen PK und dann noch diese drei Spalten mit einem Index drauf sowie eine weitere Spalte non_PK.

Ansonsten kenne ich es noch so, dass es einen technischen Key UND einen fachlichen Key gibt. Dann bist du bei deiner angesprochen Lösung mit eigenen Tabellen.

Deine drei PKs sind aber keine FKs?
 
Zuletzt bearbeitet:
Hi,

Ja, ich halte das für bedenklich. Wenn man sich mal die ersten paar Zeilen bei Wikipedia durchliest weiß man auch, warum:

Der Primärschlüssel wird üblicherweise so ausgewählt, dass er möglichst klein ist, das heißt möglichst wenige Attribute umfasst bzw. einen möglichst simplen Datentyp hat. Er sollte zeitlich stabil sein, seine Werte sollten sich also während des gesamten Lebenszyklus der betroffenen Tabellen nicht ändern, da dies auch Änderungen an den zugehörigen Fremdschlüsselwerten mit sich zöge (was durch sogenannte Kaskadierung allerdings prinzipiell möglich, aber oft aufwändig ist).

in meinen Augen ist da die Datenbankplanung schief gelaufen. Ich würde als PK eine ID / GUID nutzen.

Warum genau hat man sich für diese Werte als (Primär)Schlüssel entschieden?

VG,
Mad
 
Primary Keys sollten im Idealfall kein String sein. Außerdem muss ich den Vorpostern zustimmen - würde ebenfalls eine (GU)ID verwenden. Den Rest über Foreign Keys abbilden
 
Was meint ihr genau? So etwas hier?

Code:
|-----+------------+------------+------------|
| AID | noMorePK_A | noMorePK_B | noMorePK_C |
|-----+------------+------------+------------|
| 1   | "A"        | "B"        | "C"        |
|-----+------------+------------+------------|

|-----+--------|
| AID | non_PK |
|-----+--------|
| 1   | "wert" |
|-----+--------|

Aber wenn ich jetzt anfange, das zu zerlegen, wird es immer sinnanzweifelnder.

Ich möchte Änderungen sofort für alle haben:

Code:
|------+------+------+---------------------|
| PK_A | PK_B | PK_C | non_PK              |
|------+------+------+---------------------|
| "A"  | "B"  | "C"  | "wert"              |
| "A"  | "B"  | "D"  | "Andererwert"       |
| "A"  | "B"  | "E"  | "WiederAndererWert" |
|------+------+------+---------------------|
Ich möchte, dass, wenn sich der Wert "A" in der ersten Zeile von PK_A ändert, z.B. auf den Wert "Z", sich auch automatisch auch die Werte der zweiten und dritten Zeile für die Spalte PK_A auf "Z" ändern.

Selbiges gilt auch für PK_B und PK_C. Das lässt sich aber nur durch künstliche PKs realisieren. Aber das wird das extrem eklig und vllt. sogar dumm? Denn ich müsste für jeden PK eine Tabelle anlegen.

Beispiel:

Code:
|--------+-------+-------+---------------------|
| A (PK) | B(PK) | C(PK) | Value               |
|--------+-------+-------+---------------------|
| "A"    | "B"   | "C"   | "wert"              |
| "A"    | "B"   | "D"   | "Andererwert"       |
| "A"    | "B"   | "E"   | "WiederAndererWert" |
|--------+-------+-------+---------------------|

Diese Tabelle zerlegt in:

Tabelle A
|-----------+-----|
| A_ID (PK) | A   |
|-----------+-----|
| 0         | "A" |
|-----------+-----|

Tabelle B
|-----------+-----|
| B_ID (PK) | B   |
|-----------+-----|
| 0         | "B" |
|-----------+-----|

Tabelle C
|-----------+-----|
| C_ID (PK) | C   |
|-----------+-----|
| 0         | "C" |
| 1         | "D" |
| 2         | "E" |
|-----------+-----|

Tabelle Gesamt
|----------------+----------------+----------------+---------------------|
| A_ID (PK & FK) | B_ID (PK & FK) | C_ID (PK & FK) | Value               |
|----------------+----------------+----------------+---------------------|
| 0              | 0              | 0              | "wert"              |
| 0              | 0              | 1              | "Andererwert"       |
| 0              | 0              | 2              | "WiederAndererWert" |
|----------------+----------------+----------------+---------------------|

Jetzt bin ich gegen eine Änderung in Tabelle A gefeit. Ändert sich "A" in "Z", gilt das für alle Einträge in Tabelle Gesamt

Jetzt musste ich deswegen jedoch 3 extra Tabellen anlegen. War das sinnvoll?

EDIT: Die Tabellen wurden von mir korrigiert.
 
Zuletzt bearbeitet von einem Moderator:
Was mich noch interessiert ist folgendes:

Ich habe eine Tabelle mit 3 Primärschlüssel.[...]

falsch, würde ich sagen, denn sonst würde

Code:
| PK_A | PK_B | PK_C | non_PK              |
--------------------------------------------
| "A"  | "B"  | "D"  | "Andererwert"       |
| "A"  | "B"  | "D"  | "WiederAndererWert" |

ein Fehler werfen, da es die selbe PK Kombination ist.
Von daher brauchst du schon einen wirklich eindeutigen Schlüssel.

Und wenn deine Anforderung ist, dass du A ändern kannst und das in allen Sätzen passieren soll, wirst du um das FK Gekröse nicht drumherum kommen.

Grüße

J
 
Ja deine Letzte Tabelle macht schon mehr Sinn.
Um welche Strings handelt es sich hier?

Das was du hier machst nennt sich Datenbank Normalisierung (wiki).
Zumindest die zweite Normalform sollte es schon sein.

Und indexiere dein Char-Feld in den Auflösungstabellen

greetz
 
FKs machen und die eigentlichen Daten in einer eigenen Tabelle halten. Sollte eigentlich einfach umsetzbar sein.
 
@JenZor
War ein Flüchtigkeitsfehler. Sollte natürlich ein "E" in der dritten Zeile stecken.

@alle
Danke für die Hilfe. Ich habe die Tabelle nun sinnvoll normalisieren können. ;)
 
Zurück
Oben