Wie kann diese Einschränkung in einem Datenbankschema ausgedrückt werden?

7

Ich habe die folgenden funktionalen Abhängigkeiten, die in BCNF sind:

a,b -> c
a -> d
b -> d

Mit der zusätzlichen Einschränkung, dass nein aund bsollte mit a kombiniert werden c, wo aund bhaben unterschiedliche ds.

Beispiel:

a | d   b | d   a | b | c
-----   -----   ---------
1 | 3   5 | 3   1 | 5 | 6
2 | 4           2 | 5 | 7

Die erste Zeile in a,b,cist erlaubt ( 1->3, 5->3), aber die zweite Zeile ist verboten, da ( 2->4, 5->3) 4 != 3.

Diese zusätzliche Einschränkung kann zwei Auswirkungen auf meine Daten haben. Für jeden a,b,cgibt es zwei redundante Möglichkeiten, die zu bestimmen d. Es kann Daten geben, die gegen die Einschränkung verstoßen. Wie kann mein Schema diese zusätzliche Einschränkung widerspiegeln?

johannes
quelle

Antworten:

3

Kurz gesagt, erstellen Sie eine, ASSERTIONum sicherzustellen, dass zu keinem Zeitpunkt gegen die Geschäftsregel verstoßen werden kann, z. B. Full Standard SQL-92-Syntax:

CREATE TABLE T1
(
 a INTEGER NOT NULL, 
 d INTEGER NOT NULL, 
 UNIQUE (a, d)
);

CREATE TABLE T2
(
 b INTEGER NOT NULL, 
 d INTEGER NOT NULL, 
 UNIQUE (b, d)
);

CREATE TABLE T3
(
 a INTEGER NOT NULL,
 b INTEGER NOT NULL, 
 c INTEGER NOT NULL, 
 UNIQUE (a, b, c)
);

CREATE ASSERTION no_a_and_b_should_be_combined_with_a_c_where_a_and_b_have_different_ds
   CHECK (
          NOT EXISTS (
                      SELECT *
                        FROM T3
                       WHERE NOT EXISTS (
                                         SELECT T1.d
                                           FROM T1
                                          WHERE T1.a = T3.a 
                                         INTERSECT        
                                         SELECT T2.d
                                           FROM T2
                                          WHERE T3.b = T3.b 
                                        )
                     )
         );

Die schlechte Nachricht ist, dass kein kommerzielles (oder anderweitig?) SQL-Produkt unterstützt wird CREATE ASSERTION.

Die meisten industrietauglichen SQL-Produkte unterstützen Trigger: Sie können die oben genannten Punkte in einem Trigger für jede zutreffende Tabelle implementieren . MS Access ist das einzige mir bekannte kommerzielle Produkt, das Unterabfragen in Bezug auf CHECKEinschränkungen unterstützt, aber ich halte es nicht für industrietauglich. Es gibt weitere Problemumgehungen, z. B. das Erzwingen, dass Benutzer Tabellen nur über gespeicherte Prozeduren aktualisieren, von denen gezeigt werden kann, dass sie die Datenbank niemals in einem unzulässigen Zustand verlassen.

eines Tages, wenn
quelle
Die Prüfbedingung kann auch eine UDF aufrufen, die diese Abfrage ausführt. Dies ist jedoch keine praktische Lösung. Wie Sie bereits bemerkt haben, unterstützen die meisten RDBMS-Plattformen diese Lösung entweder nicht oder mit vielen Einschränkungen .
Nick Chammas
4

Kurz gesagt, führen Sie din die dritte Tabelle ein, um Vanille-Fremdschlüsseleinschränkungen zu aktivieren, z. B. Transitional SQL-92-Syntax:

CREATE TABLE T1
(
 a INTEGER NOT NULL, 
 d INTEGER NOT NULL, 
 UNIQUE (a, d)
);

CREATE TABLE T2
(
 b INTEGER NOT NULL, 
 d INTEGER NOT NULL, 
 UNIQUE (b, d)
);

CREATE TABLE T3
(
 a INTEGER NOT NULL,
 b INTEGER NOT NULL, 
 c INTEGER NOT NULL, 
 d INTEGER NOT NULL, 
 UNIQUE (a, b, c),
 FOREIGN KEY (a, d) REFERENCES T1 (a, d), 
 FOREIGN KEY (b, d) REFERENCES T2 (b, d)
);
eines Tages, wenn
quelle
Dies gibt mir unerwünschte Redundanz. Dieses Schema wäre nicht mehr in BCNF.
Johannes
@johannes - Es ist ein geringer Preis, um Ihre Einschränkungen auf effiziente und einfache Weise durchzusetzen. In der Praxis ist der einzige Nachteil dieses Ansatzes die zusätzlichen Speicherkosten für die wiederholte d-Spalte in T3, was ehrlich gesagt vernachlässigbare Kosten sind. BCNF ist nicht das A und O des Datenbankdesigns, insbesondere wenn Sie implementieren und nicht nur abstrakt entwerfen.
Nick Chammas
3

"Also ist deine Antwort" es ist nicht möglich "?"

Viele Dinge sind möglich. In Ihrem speziellen Fall scheint es mir, dass die Durchsetzung Ihrer "zusätzlichen" Einschränkung erreicht werden kann, indem die Datenbank in einer Tabelle (4 Spalten) gehalten wird. Dies garantiert Ihnen, dass jedes kombinierte a, b immer demselben d entspricht (da es immer nur ein einziges d geben kann). Der Preis, den Sie zahlen, ist, dass es keinen "natürlichen" Weg mehr gibt (dh einen, der eine unmittelbare Folge der sehr logischen Struktur der Datenbank selbst ist), der Ihre a-> d- und b-> d-FDs "automatisch" erzwingt. .

Es ist eine bekannte Tatsache, dass der klassische Prozess der Normalisierung durch Zerlegung manchmal erfordert, dass bestimmte FDs als Datenbankeinschränkung wiederhergestellt werden, da die Regel im zerlegten Entwurf nicht mehr als FD angegeben werden kann. Ihr spezieller Fall scheint ein solcher zu sein, bei dem Sie die Wahl zwischen einem Entwurf haben, der "automatisch" a-> d und b-> d erzwingt, bei dem Sie jedoch zusätzliche Anstrengungen unternehmen müssen, um Ihre zusätzliche Einschränkung durchzusetzen, oder einem Entwurf, bei dem dies der Fall ist "automatisch" erzwingt Ihre zusätzliche Einschränkung, aber wo Sie zusätzliche Arbeit leisten müssen, um [die Einschränkungen entsprechend] Ihrer a-> d- und b-> d-FDs durchzusetzen.

In Ihrem speziellen Fall ist es möglich, ALLE von Ihnen genannten Einschränkungen nur durch die Datenbankstruktur durchzusetzen, wenn Sie die Lösung von onedaywhen verwenden. (A) Dies ist jedoch nur eine Lösung für bestimmte Fälle wie Ihr Beispiel. (B) Der Preis, den Sie zahlen, ist eine erhöhte Redundanz und daher eine zusätzliche Komplexität bei der Aktualisierung Ihrer Datenbank (und bestimmte Aktualisierungen sind möglicherweise nicht möglich !!!). und (c) es bleibt immer noch eine Tatsache, dass nicht alle denkbaren Datenbankbeschränkungen als FD ausgedrückt werden können.

(Entschuldigung für die Veröffentlichung einer zweiten Antwort. Bei meinem Stackoverflow-Login kann ich hier keine Kommentare abgeben.)

Erwin Smout
quelle