Wird die Verwendung mehrerer eindeutiger Einschränkungen für eine einzelne Tabelle als schlechtes Design angesehen?


8

Ich habe mir die INSERT INTO .. ON CONFLICT (..) DO UPDATE ..Syntax von PostgreSQL angesehen und festgestellt, dass Sie damit nicht mehrere eindeutige Einschränkungsprüfungen durchführen können. Ich meine, Sie verweisen entweder mit den Spaltennamen auf einen zusammengesetzten eindeutigen Index ON CONFLICT (Name, Symbol)(wenn der eindeutige Index für diese beiden Spalten definiert ist), oder Sie verwenden den Primärschlüssel. Wenn Sie zwei separate eindeutige Indizes für die Spalten definieren, können Sie nur nach einem suchen.

CREATE TABLE student
    (Id int primary key, Name varchar(50), Symbol varchar(50),
      CONSTRAINT col1_unique UNIQUE (Name),
      CONSTRAINT col2_unique UNIQUE (Symbol)
    ); 

INSERT INTO student
    (Id, Name, Symbol)
VALUES
    (1, 'John', 'J'),
    (2, 'David', 'D'),
    (3, 'Will', 'W');

INSERT INTO student
    (Id, Name, Symbol)
VALUES
    (4, 'Jeremy', 'J')
   on conflict(Name) DO UPDATE
   set Name = 'Jeremy';

Könnte einen Fehler auslösen und sagen, dass Jes sich um ein Duplikat handelt. Dieses Beispiel ist jedoch einfach ein schlechtes Design, da sich das Symbol in einer anderen Tabelle befinden und über eine Eins-zu-Viele-Beziehung mit der Schülertabelle verbunden sein sollte. Aus diesem Grund frage ich mich, ob PostgreSQL möglicherweise so on conflictkonzipiert wurde, weil Sie die Tabellen IMMER so umstrukturieren können, dass es nur einen einzigen eindeutigen Index gibt. Ist es wahr oder gibt es einen anderen Grund?

Beispiel Geige: http://www.sqlfiddle.com/#!17/9c0ce


Sie können die Tabellen IMMER so umstrukturieren, dass es nur einen einzigen eindeutigen Index gibt. Es gibt EntityA und EntityB. Es gibt jeweils 2 Instanzen. Jede EntityA-Instanz kann mit jeder EntityB-Instanz kombiniert werden. Es gibt also zwei mögliche Kombinationen, bei denen alle Instanzen verwendet werden. Eine dieser Kombinationen wird realisiert und muss gespeichert werden. Versuchen Sie nun, ein Schema zu erstellen, in dem keine Tabelle mit 2 Eindeutigkeiten mit allen Einschränkungen vorhanden ist, die illegale Daten verhindern.
Akina

@Akina Ich habe deinen Punkt verpasst. Wenn zwei Entitäten über eine Viele-zu-Viele-Beziehung verbunden sind, erstellen Sie eine Verknüpfungstabelle, in der ihre Fremdschlüssel gespeichert sind, sodass keine Tabelle mit zwei eindeutigen Indizes vorhanden ist.
Appl3r

Eine Instanz kann nur einmal verwendet werden. Sie müssen also zwei eindeutige Indizes in einer verknüpften Tabelle haben (von jeder Entität separat), um die Verwendung der bereits verwendeten Instanz zu verhindern.
Akina

Das stimmt zwar, aber das ist ziemlich ärgerlich: siehe das Beispiel in der Antwort von Michael Green. Das Aufteilen einer so einfachen Tabelle in 4 Tabellen bereitet definitiv Kopfschmerzen, da es sich um ein einfaches Wörterbuch handelt und Sie nicht die Option "ON CONFLICT" benötigen sollten.
Walfrat

Antworten:


8

Es gibt immer die sechste oder Domänenschlüssel-Normalform. Hier wird jede Nicht-Schlüsselspalte zu einer eigenen Tabelle. Die 3NF-Tabelle T (Schlüssel, Spalte 1, Spalte 2, ..) wird also zu T1 (Schlüssel, Spalte 1), T2 (Schlüssel, Spalte 2) usw. Für die neuen Tabellen, die Eindeutigkeit erfordern, kann sie deklariert werden.

Ich denke jedoch, dass es vollkommen in Ordnung ist, mehrere eindeutige Einschränkungen für eine Tabelle zu haben. Nehmen Sie zum Beispiel eine Tabelle mit Ländern. Dies hätte beispielsweise eine ID, den Namen, den ISO-Code, die Hauptstadt und einige andere. Jeder dieser ersten vier wird einzigartig sein. Wenn wir möchten, dass unser System darauf beruht, dass jedes System einzigartig ist, sollten wir meines Erachtens für jedes System eindeutige Einschränkungen definieren. Dies erzwingt Wahrheiten über die Daten, auf die sich alle Verbraucher verlassen können.


Denken Sie, dass das Postgresql-Design dann nur das Ergebnis von Kurzsichtigkeit ist? Oracle, SQL Server, DB2 und andere bieten alle die Möglichkeit, alle eindeutigen Schlüssel in einer solchen Situation zu berücksichtigen (mithilfe der MERGEAnweisung). Die Seite ON CONFLICT DO UPDATE wurde erst in 9.5 hinzugefügt und ist viel eingeschränkter.
Appl3r

1
@ appl3r es ist nur ein Implementierungsdetail. Sie können darauf ON CONFLICT DO NOTHINGverzichten, eindeutige Einschränkungen zu erwähnen, und alle werden berücksichtigt (und nichts unternommen). Wenn Sie dies tun möchten, müssen ON CONFLICT DO UPDATESie eine Spalte oder eine Einschränkung deklarieren und nur eine. Die Einschränkung wird möglicherweise in zukünftigen Versionen aufgehoben.
Ypercubeᵀᴹ

Ich bin ein bisschen verwirrt von Ihrem ersten Absatz. Angenommen, wir teilen die Student-Tabelle (ID, Name, Symbol) des OP in S1 (ID, Name) und S2 (ID, Symbol) auf, um zu versuchen, sie in DK / NF zu verwandeln. Was wären die (Domänen- und) Hauptbeschränkungen für S2 und wie würden sie sicherstellen, dass jeder Schüler sowohl eine einzige eindeutige ID als auch ein einziges eindeutiges Symbol hat?
Ilmari Karonen

1
Die Frage war (Art von) "Wenn mehrere EINZIGARTIGE Indizes in Ordnung sind, warum erfordert PostgreSQL, dass ein Arbiter-Index angegeben wird, ON CONFLICT ... DO UPDATEund leider spricht diese Antwort diesen Punkt nicht an.
AndreKR

@AndreKR adressiert das (fettgedruckte): " Wurde (diese Postgres-Funktion) auf diese Weise entworfen, weil Sie die Tabellen IMMER so umstrukturieren können, dass es nur einen einzigen eindeutigen Index gibt?" Sie können sicherlich eine weitere Antwort hinzufügen, die den von Ihnen erwähnten Punkt anspricht
ypercubeᵀᴹ
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.