Frage

Wenn Fremdschlüssel in SQL Server einrichten, unter welchen Umständen sollten Sie es Kaskade haben auf löschen oder zu aktualisieren, und was ist die Begründung dahinter?

Dies ist wahrscheinlich auf andere Datenbanken gilt auch.

Ich suche vor allem für konkrete Beispiele für jedes Szenario, vorzugsweise von jemandem, den sie erfolgreich eingesetzt hat.

War es hilfreich?

Lösung

Zusammenfassung von dem, was ich bisher gesehen habe:

  • Einige Leute mögen gar nicht kaskadieren.

Cascade Löschen

  • Cascade löschen kann sinnvoll sein, wenn die Semantik der Beziehung eine exklusive beinhalten können Beschreibung „Teil ist“. Zum Beispiel ist ein Orderline Rekord Teil seines Mutterauftrages und Orderlines wird nie zwischen mehreren Aufträgen gemeinsam genutzt werden. Wenn der Orden verschwinden würde, sollte die Orderline als auch, und eine Linie ohne Auftrag ein Problem sein würden.
  • Das kanonische Beispiel für Cascade Löschen ist Someobject und SomeObjectItems, wo es keinen Sinn für einen Artikel Aufzeichnung ohne einen entsprechenden Hauptsatz existiert immer macht.
  • Sie sollten nicht verwenden Cascade löschen, wenn Sie Geschichte sind die Erhaltung oder eine „weiche / logische Löschen“ mit dem Sie nur eine gelöschte Bit Spalte auf 1 / true.

Cascade-Update

  • Cascade-Update kann sinnvoll sein, wenn Sie einen echten Schlüssel verwenden, anstatt ein Ersatzschlüssel (Identität / Autoinkrement-Spalte) über Tabellen.
  • Das kanonische Beispiel für Cascade-Update, wenn Sie einen wandelbaren Fremdschlüssel haben, wie ein Benutzername, der geändert werden kann.
  • Sie sollten nicht verwenden Cascade-Update mit Tasten, die Identität / Autoinkrement-Spalten sind.
  • Cascade-Update am besten in Verbindung mit einer einzigartigen Einschränkung verwendet.

Wenn Cascading nutzen

  • können Sie mögen eine extra starke Bestätigung zurück vom Benutzer erhalten, bevor eine Operation Kaskade erlaubt, aber es hängt von Ihrer Anwendung.
  • Cascading können Sie in Schwierigkeiten geraten, wenn Sie Ihre Fremdschlüssel falsch eingestellt. Aber Sie sollten in Ordnung sein, wenn Sie die richtigen tun.
  • Es ist nicht klug, Kaskadierung zu verwenden, bevor Sie es gründlich zu verstehen. Es ist jedoch eine nützliche Funktion, und deshalb lohnt sich die Zeit nehmen, zu verstehen.

Andere Tipps

Fremdschlüssel sind der beste Weg, referentielle Integrität einer Datenbank zu gewährleisten. Vermeiden Kaskaden durch Magie zu sein, ist wie alles in der Montage zu schreiben, weil Sie die Magie hinter Compiler nicht vertrauen.

Was ist schlecht ist die falsche Verwendung von Fremdschlüsseln, wie sie nach hinten zu schaffen, zum Beispiel.

Juan Manuel Beispiel ist das kanonische Beispiel, wenn Sie Code dort verwenden viele mehr Chancen zu verlassen unechte DocumentItems in der Datenbank vorhanden sind, die Sie kommen und beißen.

Cascading Updates sind zum Beispiel nützlich, wenn Sie Verweise auf die Daten, die durch etwas, das ändern, sagen wir ein Primärschlüssel einer Benutzer-Tabelle ist der Name, Nachname Kombination. Dann möchten Sie Änderungen in dieser Kombination zu verbreiten, wo immer sie verwiesen wird.

@Aidan, dass Klarheit Sie beziehen kommt zu einem hohen Preis, die Möglichkeit von falschen Daten in der Datenbank zu verlassen, das ist nicht klein . Für mich ist es in der Regel nur Mangel an Vertrautheit mit der DB und die Unfähigkeit zu finden, welche FKs vorhanden sind, bevor Sie mit der DB arbeitet, dass die Angst fördern. Entweder das, oder ständiger Missbrauch von Kaskade, indem es in dem die Einheiten nicht konzeptionell verwandte waren, oder wo Sie die Geschichte bewahren.

Ich benutze nie Löschungen kaskadieren.

Wenn ich etwas aus der Datenbank entfernt will ich will die Datenbank explizit sagen, was ich will herausnehmen.

Natürlich sind sie eine Funktion in der Datenbank, und es kann vorkommen, dass es in Ordnung ist, sie zu verwenden, zum Beispiel, wenn Sie eine ‚Ordnung‘ Tisch und ein ‚OrderItem‘ Tabelle können Sie die Elemente löschen möchten, wenn Sie einen Auftrag löschen.

Ich mag die Klarheit, die ich zu tun es in Code (oder gespeicherte Prozedur) erhalten, anstatt ‚Magie‘ geschieht.

Aus dem gleichen Grunde bin ich kein Fan von Triggern auch nicht.

Etwas zu bemerken ist, dass, wenn Sie eine ‚Ordnung‘ lösche werden Sie '1 row affected Bericht zurück, auch wenn die 50 ‚OrderItem die entfernt kaskadiert löschen.

Ich arbeite viel mit Cascading Löschungen.

Es fühlt sich gut zu wissen, wer für die Datenbank funktioniert vielleicht nie irgendwelche unerwünschten Daten verlassen. Wenn Abhängigkeiten wachsen ich im Diagramm in Management Studio nur die Einschränkungen ändern und ich nicht haben sp oder dataacces zwicken.

Das heißt, ich habe 1 Problem mit Cascading Löschungen und das ist zirkuläre Referenzen. Dies führt oft zu Teilen der Datenbank, die keine Cascading Löschungen haben.

Ich habe eine Menge von Datenbank-Arbeit und selten Kaskade löscht nützlich finden. Das ein Mal, die ich verwendet habe sie effektiv in einer Berichtsdatenbank, die von einem nächtlichen Job aktualisiert wird. Ich stelle sicher, dass alle geänderten Daten korrekt importiert wird durch alle Top-Level-Löschen von Datensätzen, die seit dem letzten Import geändert haben, dann die geänderten Datensätze neu einspielen und alles, was ihnen betrifft. Es rettet mich aus mit vielen komplizierter Löschungen zu schreiben, die an die Spitze meiner Datenbank von unten aussehen.

Ich glaube nicht, Kaskade löscht ganz so schlimm sein, wie löst, da sie nur Daten löschen, Trigger innen alle Arten von bösen Sachen haben kann.

Im Allgemeinen vermeide ich echte Löscht ganz und verwenden logische Löschungen (dh. Ein wenig Säule mit genannt isDeleted, der auf true gesetzt wird) statt.

Ein Beispiel ist, wenn Sie Abhängigkeiten zwischen Entitäten haben ... also: Dokument -> DocumentItems (wenn Sie Dokument löschen, DocumentItems hat keinen Grund zu existieren)

Mit Kaskade löscht in dem Sie den Datensatz mit dem FK wollen würden entfernt werden, wenn seine Bezugnahme PK Rekord entfernt wurde. Mit anderen Worten, in dem die Aufzeichnung ohne Referenzierung Datensatz bedeutungslos ist.

Ich finde Kaskade löschen nützlich, dass tote Verweise zu gewährleisten standardmäßig entfernt werden, anstatt null Ausnahmen führen.

ON DELETE CASCADE:

Wenn Sie Zeilen in untergeordneter Tabelle gelöscht werden Wenn Zeile entspricht, wird gelöscht in übergeordneter Tabelle.

Wenn auf Kaskade löschen wird nicht verwendet, dann wird ein Fehler für angehoben werden referentielle Integrität .

ON-Update Cascade:

Wenn Sie Änderung des Primärschlüssels in aktualisiert werden Fremdschlüssel

Ein Grund in einer Kaskade zu setzen löscht (anstatt es in dem Code zu tun) ist die Leistung zu verbessern.

Fall 1: Mit einer Kaskade löschen

 DELETE FROM table WHERE SomeDate < 7 years ago;

Fall 2: Ohne eine Kaskade löschen

 FOR EACH R IN (SELECT FROM table WHERE SomeDate < 7 years ago) LOOP
   DELETE FROM ChildTable WHERE tableId = R.tableId;
   DELETE FROM table WHERE tableId = R.tableid;
   /* More child tables here */
 NEXT

Zweitens, wenn Sie in einem extra Kindertisch mit einer Kaskade hinzufügen löschen, den Code in Fall 1 hält arbeiten.

würde ich nur in einer Kaskade setzen, wo die Semantik der Beziehung „Teil“ ist. Ansonsten irgendein Idiot wird die Hälfte der Datenbank löschen, wenn Sie tun:

DELETE FROM CURRENCY WHERE CurrencyCode = 'USD'

Ich habe von DBAs gehört und / oder „Unternehmenspolitik“, das „On Delete Cascade“ (und andere) rein wegen der schlechten Erfahrungen in der Vergangenheit verbietet die Verwendung. In einem Fall schrieb ein Mann drei Trigger, die sie am Ende rufen. Drei Tage zu erholen in einem vollständigen Verbot von Trigger geführt, die alle aufgrund der Aktionen von einer Idjit.

Natürlich manchmal Trigger werden benötigt anstelle von „On löschen Kaskade“, wie wenn einige Child-Daten erhalten werden muss. Aber in anderen Fällen seine volle Gültigkeit des auf Löschen Kaskadenverfahren zu verwenden. Ein wesentlicher Vorteil der „On löschen Kaskade“ ist, dass es alle Kinder erfasst; eine benutzerdefinierte geschrieben Trigger / Speicher-Prozedur nicht, wenn es nicht richtig codiert.

Ich glaube, der Entwickler erlaubt sein soll, die Entscheidung zu treffen, basierend auf, was die Entwicklung ist und was die Spezifikation sagt. Ein Teppich Verbot einer schlechten Erfahrung beruhen sollte nicht die Kriterien sein; der „Niemals“ Denkprozess ist besten drakonisch. Ein Urteil nennen muss jedes Mal durchgeführt werden, und Änderungen der Geschäftsmodelländerungen vorgenommen.

Ist das nicht das, was Entwicklung ist alles?

Ich versuche, Löschungen oder Änderungen zu vermeiden, dass ich nicht explizit in SQL Server anfordern.

Entweder durch Kaskadierung oder durch die Verwendung von Triggern. Sie neigen dazu, dich in den Arsch einige Zeit auf der ganzen Linie zu beißen, entweder bei dem Versuch, einen Fehler aufzuspüren oder wenn Performance-Probleme zu diagnostizieren.

Wo ich sie verwenden würde, ist die Konsistenz bei der Gewährleistung für nicht sehr viel Aufwand. Um den gleichen Effekt zu erhalten würden Sie gespeicherte Prozeduren verwenden.

ich, wie jeder andere auch hier feststellen, dass Kaskade Löschungen sind wirklich nur marginal nützlich (es ist wirklich nicht so viel Arbeit zu referenzierten Daten in anderen Tabellen löschen - wenn es viele Tische sind, können Sie einfach automatisieren dies mit einem Skript) aber wirklich ärgerlich, wenn jemand versehentlich Kaskade löscht einige wichtige Daten, die nur schwer wieder herzustellen.

Der einzige Fall, wo ich verwenden würde, ist, wenn die Daten in der Tabelle Tabelle hoch gesteuert werden (zB eingeschränkte Berechtigungen) und nur aktualisiert oder durch einen kontrollierten Prozess gelöscht werden (wie ein Software-Update), die überprüft wurde.

Eine Löschung oder Aktualisierung auf S, die einen Fremdschlüssel-Wert in einigen Tupeln von R gehandhabt werden kann, in einem von drei Arten gefunden entfernt:

  1. Die Ablehnung
  2. Die Ausbreitung
  3. nullification.

Die Ausbreitung als Kaskadierung bezeichnet wird.

Es gibt zwei Fälle:

‣ Wenn ein Tupel in S gelöscht wurde, löschen Sie die R-Tupel, die ihm vorgelegt.

‣ Wenn ein Tupel in S aktualisiert wurde, aktualisieren Sie den Wert in den R Tupel, die sich darauf beziehen.

Wenn Sie auf einem System mit vielen verschiedenen Modulen in verschiedenen Versionen arbeiten, kann es sehr hilfreich sein, wenn die Kaskade gelöschte Elemente sind Teil der / des PK Inhaber gehört. Sonst würden alle Module sofort Patches benötigen, um ihre abhängigen Elemente zu bereinigen, bevor Sie den PK Eigentümer löschen oder die Fremdschlüsselbeziehung würde vollständig weggelassen werden, möglicherweise Tonnen Müll in das System zu verlassen, falls die Bereinigung nicht korrekt durchgeführt wird.

Ich habe gerade eingeführt Kaskade für eine neue Verknüpfungstabelle löscht zwischen zwei bereits vorhandenen Tabellen (die Kreuzung nur löschen), nach Kaskade von seit geraumer Zeit entmutigt worden löschen. Es ist auch nicht so schlecht, wenn Daten verloren geht.

Es ist jedoch eine schlechte Sache auf ENUM-ähnliche Liste Tabellen: jemand löscht Eintrag 13 - gelb aus der Tabelle „Farben“, und alle gelben Elemente in der Datenbank gelöscht. diese manchmal auch in einer Lösch-all-Insert-all Weise aktualisiert werden, was die Integrität referentielle völlig verzichtet. Natürlich ist es falsch, aber wie werden Sie eine komplexe Software ändern, die seit vielen Jahren läuft, mit Einführung der wahren referentielle Integrität bei Risiko unerwarteter Nebenwirkungen zu sein?

Ein weiteres Problem ist, wenn Original-Fremd werden Schlüsselwerte auch nach dem Primärschlüssel gelöscht wurde gehalten werden. Man kann eine Grabstein-Spalte erstellen und ein EIN für die ursprüngliche FK SET NULL Option DELETE, aber dies wiederum erfordert Trigger oder spezifischen Code, um die redundanten beizubehalten (außer nach PK Streichung) Schlüsselwert.

Cascade Löschungen sind extrem nützlich, wenn logische Super-Typ und Untertyp Entitäten in einer physischen Datenbank zu implementieren.

Wenn getrennte Super-Typ und Untertyp Tabellen verwendet werden, sind physikalisch super-Arten / Unterarten zu implementieren (im Gegensatz zu rollen all Untertyp-Attribute in eine einzige physische Super-Typ-Tabelle), gibt es eine eins-zu-eins-Beziehung zwischen diesen Tabellen und die Frage wird dann, wie zwischen diesen Tabellen sind die Primärschlüssel 100% synchron zu halten.

Cascade Löschungen kann ein sehr nützliches Werkzeug sein:

1) Stellen Sie sicher, dass ein Super-Typ Datensatz löschen auch die entsprechenden Einzeluntertyp Datensatz löscht.

2) Stellen Sie sicher, dass alle Lösch eines Sub-Typ Datensatz löscht auch den Super-Typ Rekord. Dies wird durch die Implementierung eines erreicht „anstelle-von“ löschen Trigger auf der Untertyp-Tabelle, die geht und löscht den entsprechenden Super-Typ Datensatz, der wiederum Kaskade löscht den Untertypsatz.

Kaskade Mit löscht auf diese Weise wird sichergestellt, dass keine Waise Super-Typ oder Untertyp Aufzeichnungen existieren immer, unabhängig davon, ob Sie den Super-Typ Datensatz zuerst löschen oder die Sub-Typ Datensatz zuerst.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top