2008-10-22 9 views

Antwort

22

Gerade von the manual ...

Wir wissen, dass die Fremdschlüssel Anlegen von Aufträgen nicht zulassen, die auf Produkte beziehen sich nicht. Was aber, wenn ein Produkt nach der Erstellung einer Bestellung entfernt wird, die darauf verweist? Mit SQL können Sie das auch handhaben. Intuitiv haben wir ein paar Optionen:

Disallow eine referenzierte Produkt löschen

die Aufträge löschen und

Etwas anderes?

CREATE TABLE order_items (
product_no integer REFERENCES products ON DELETE RESTRICT, 
order_id integer REFERENCES orders ON DELETE CASCADE, 
quantity integer, 
PRIMARY KEY (product_no, order_id) 
); 

Beschränkung und Löschungen Kaskadierung sind die beiden am häufigsten verwendeten Optionen. RESTRICT verhindert das Löschen einer referenzierten Zeile. NO ACTION bedeutet, dass, wenn Zeilen, die referenziert werden, noch vorhanden sind, wenn die Einschränkung aktiviert ist, ein Fehler auftritt; Dies ist das Standardverhalten, wenn Sie nichts angeben. (Der wesentliche Unterschied zwischen diesen beiden Optionen besteht darin, dass KEINE AKTION die Prüfung bis zu einem späteren Zeitpunkt in der Transaktion verzögern kann, während RESTRICT dies nicht tut.) CASCADE gibt an, dass Zeilen, die auf diese Zeile verweisen, automatisch gelöscht werden auch. Es gibt zwei weitere Optionen: SET NULL und SET DEFAULT. Diese bewirken, dass die referenzierenden Spalten auf Nullen bzw. Standardwerte gesetzt werden, wenn die referenzierte Zeile gelöscht wird. Beachten Sie, dass dies Sie nicht davon entbindet, Einschränkungen zu beachten. Wenn eine Aktion beispielsweise SET DEFAULT angibt, aber der Standardwert den Fremdschlüssel nicht erfüllt, schlägt der Vorgang fehl.

Analog zu ON DELETE gibt es auch ON UPDATE, das aufgerufen wird, wenn eine referenzierte Spalte geändert (aktualisiert) wird. Die möglichen Aktionen sind die gleichen.

edit: Sie können einen Blick auf diese Frage im Zusammenhang nehmen wollen: When/Why to use Cascading in SQL Server?. Die Konzepte hinter den Fragen/Antworten sind die gleichen.

0

Ich habe eine PostGreSQL-Datenbank und ich benutze auf Löschen, wenn ich einen Benutzer habe, den ich aus der Datenbank lösche, und ich muss seine Informationen aus anderen Tabellen löschen. Auf diese Weise muss ich nur 1 löschen und FK, die ON löschen hat, löscht Informationen aus anderen Tabellen.

Sie können das gleiche mit ON Update tun. Wenn Sie die Tabelle aktualisieren und das Feld einen FK mit On Update hat, werden Sie, wenn eine Änderung am FK vorgenommen wird, in der FK Tabelle bemerkt.

0

Was Daok sagt, ist wahr ... es kann ziemlich bequem sein. Auf der anderen Seite kann das automatische Vorkommen von Dingen in der Datenbank ein echtes Problem sein, besonders wenn es um die Eliminierung von Daten geht. Es ist möglich, dass jemand in der Zukunft darauf zählen wird, dass FKs die Löschung von Eltern verhindern, wenn es Kinder gibt und nicht erkennen, dass Ihre Verwendung von On Delete Cascade nicht nur das Löschen verhindert, sondern riesige Datenmengen in Dutzenden von andere Tische verschwinden dank eines Kaskadierfalles.

@ Arthurs Kommentar.

Je häufiger "versteckte" Dinge in der Datenbank passieren, desto unwahrscheinlicher wird es, dass jemand jemals einen guten Überblick darüber hat, was vor sich geht.Auslöser (und dies ist im Wesentlichen ein Auslöser) können dazu führen, dass meine einfache Aktion zum Löschen einer Zeile weit reichende Konsequenzen für meine gesamte Datenbank hat. Ich gebe eine Delete-Anweisung aus und 17 Tabellen sind mit Kaskaden von Triggern und Constraints betroffen, und nichts davon ist für den Herausgeber des Befehls sofort ersichtlich. OTOH, Wenn ich die Löschung des Elternteils und aller seiner Kinder in eine Prozedur lege, dann ist es sehr einfach und klar für jeden, GENAU zu sehen, was passieren wird, wenn ich den Befehl ausstelle.

Es hat absolut nichts damit zu tun, wie gut ich eine Datenbank entwerfe. Es hat alles mit den operativen Problemen zu tun, die durch Trigger ausgelöst werden.

+1

Ich denke nicht, dass dies ein Problem ist, wenn das Schema korrekt entworfen wird. in der Regel Kinder (FKs) von Daten sind ohne ihre Eltern nicht wirklich nützlich. –

+0

Das ist eine vernünftige Aussage. Aber je mehr Dinge ohne Absicht geschehen, desto weniger erfolgreich ist die Datenbank. siehe oben in der Antwort. –

+0

Sie müssen entscheiden, ob der DB nur ein Daten-Dump für eine Anwendung ist oder ob der DB selbst Wert/Bedeutung hat. Wenn eine Datenbank ohne App arbeiten kann - direkte Datenlast, direkter Abfragezugriff usw. - müssen Sie die Regeln in der DB-Schicht definieren, da die App nicht dazu da ist, diese Dinge für Sie zu erledigen. Meiner Erfahrung nach neigen Juniorentwickler dazu, die DB als von einer App gesteuert zu behandeln, während ältere Entwickler (die zu oft gebrannt wurden) die DB so entwerfen, dass sie auf sich selbst gestellt ist. Denken Sie daran, DBs können weiterleben, lange nachdem die App weg ist. Dies ist nur das Prinzip der Kapselung, angewendet auf Datenbanken. –

0

Anstatt die Methode zu schreiben, die für die gesamte Arbeit, die Kaskadenlöschung oder die Kaskadenaktualisierung erforderlich ist, können Sie stattdessen einfach eine Warnmeldung schreiben. Viel einfacher als das Rad neu zu erfinden, und macht es dem Kunden klar (und neue Entwickler, die den Code aufheben)

Verwandte Themen