Gibt es eine Zeit, in der wir das kaskadierende Löschen vermeiden sollten?


11

In SQL Server 2008 gibt es eine Primärtabelle, die mit drei anderen untergeordneten Tabellen durch eine Beziehung von 1 zu vielen verknüpft ist. Wir denken also darüber nach, Cascading delete in der Primärtabelle zu verwenden, damit alle Datensätze in der untergeordneten Tabelle entfernt werden, wenn der Datensatz aus der Primärtabelle gelöscht wird.

  1. Ist das kaskadierende Löschen hier eine richtige Wahl?
  2. Wann sollte kaskadierende Detele nicht verwendet werden?

3
Niemand kann dies beantworten, ohne Ihren Anwendungsfall zu kennen. Beim kaskadierenden Löschen besteht immer die Gefahr, dass Daten leicht gelöscht werden. Grundsätzlich benutze ich es sehr selten, in Fällen, in denen dies das gewünschte Verhalten ist. Dies sind im Allgemeinen stark modifizierte Tabellen.
Dekso

Antworten:


17

Ich bin generell vorsichtig bei kaskadierten Löschvorgängen (und anderen automatischen Aktionen, die Daten löschen oder beschädigen könnten), entweder über Trigger oder ON <something> CASCADE. Solche Einrichtungen sind sehr leistungsfähig, aber auch potenziell gefährlich.

  • Ist das kaskadierende Löschen hier eine richtige Wahl?

Es würde sicherlich das tun, wonach Sie suchen: Entfernen Sie verwandte Datensätze, wenn ein übergeordneter Datensatz entfernt wird, ohne dass Sie eine andere Logik implementieren müssen, um sicherzustellen, dass Kinder zuerst entfernt werden, wodurch Ihr Code präziser wird. Alle Aktionen werden in eine implizite Transaktion eingeschlossen. Wenn also etwas blockiert, löscht das Kind die gesamte Operation, wodurch die referenzielle Integrität mit geringem oder keinem zusätzlichen Codierungsaufwand aufrechterhalten wird.

Stellen Sie sicher, dass Ihre Verwendung von kaskadierten Löschvorgängen und anderen Aktionen "hinter den Kulissen" gut dokumentiert ist, damit zukünftige Systembetreuer sich dessen voll bewusst sind.

  • Wann sollte kaskadierende Detele nicht verwendet werden?

Es sollte nicht verwendet werden, wenn Sie wie ich paranoid sind! Ein wichtiger Punkt, den Sie berücksichtigen sollten, sind die anderen Entwickler, die derzeit oder in Zukunft an Ihrem Code / Ihrer Datenbank arbeiten (daher der obige Kommentar zur Dokumentation "versteckter" Verhaltensweisen).

Es ist ganz in meiner Erfahrung gemeinsam für unerfahrene Menschen zu verwenden , DELETEdann re- INSERTzu aktualisieren , um Reihen, vor allem , wenn , was sie wirklich wollen , ist ein MERGE/ UPSERTBetrieb (Update vorhandene Zeilen und neue zu schaffen , in der eine Zeile mit einem bestimmten Schlüssel nicht existiert) und das DBMS unterstützt Merge / Upsert nicht (oder sie wissen nichts von seiner Unterstützung). Ohne kaskadierte Aktionen ist dies absolut sicher (oder es tritt ein Fehler auf, wenn die Datenintegrität gefährdet wird), aber wenn jemand dies für Zeilen in einer übergeordneten Tabelle tut, in denen verweisende FKs vorhanden sindON DELETE CASCADEWenn dann festgelegt wird, werden verwandte Daten als Ergebnis des anfänglichen Löschens gelöscht und nicht ersetzt - so gehen Daten verloren (nicht, dass die Kaskade mit dem Löschvorgang stattfindet, selbst wenn das Löschen und das anschließende Einfügen in explizite Transaktionen eingeschlossen sind - dies wird nicht der Fall sein Warten Sie ab, ob die Transaktion die Zeilen in der übergeordneten Tabelle in nachfolgenden Anweisungen ersetzt.) Die Kaskade kann über andere Beziehungsschiffe fortgesetzt werden (z. B. Löschen eines leitenden Vorgesetzten, Löschen seines Teams durch Kaskade, Löschen der Teams seiner Teams durch Kaskade). Alle verfolgten Datensätze für all diese Personen werden durch Kaskade gelöscht, ...). Ohne aktivierte Kaskadierung würde hier nur ein Fehler angezeigt, anstatt dass die Daten stillschweigend verloren gehen.


Wird es Auswirkungen auf die Leistung geben? Als wäre es besser als eine Kaskade, eine Sperre zu erwerben und manuell zu löschen?
Ramesh

Ich würde davon ausgehen, dass es kaum Unterschiede gibt, vorausgesetzt, Sie haben den manuelleren Prozess in eine explizite Transaktion eingebunden, die Sie aus Gründen der Konsistenz durchführen sollten. Sowohl die manuelle als auch die automatische (Kaskaden-) Methode werden natürlich von Sperr- und Isolationsstufen beeinflusst, sobald die Parallelität berücksichtigt wird.
David Spillett

4

Ich denke, die Antwort läuft darauf hinaus, ob es für Ihre Situation Sinn macht oder nicht, es hängt davon ab . Ist es für Ihre Situation sinnvoll, dass die Zeilen in der 'untergeordneten' Tabelle erhalten bleiben, wenn die entsprechenden 'primären' Zeilen entfernt werden? Wären die Daten in der untergeordneten Tabelle ohne das übergeordnete Element bedeutungslos? Wenn ja, würde das kaskadierende Löschen die referenzielle Integrität erzwingen. Möglicherweise möchten Sie untergeordnete Zeilen als Datensatz aufbewahren, als Archiv vergangener Aktivitäten (obwohl Sie diese Zeilen möglicherweise speziell für diesen Zweck in eine andere Tabelle schreiben könnten).

Ein Beispiel, das ich zur Veranschaulichung dieses Punktes verwende, ist die Beziehung zwischen Arzt und Patient. Ein Arzt kann viele Patienten haben. Ein Patient kann nur ein Patient sein, wenn er einen Arzt hat. Wenn der Arzt geht (die Praxis verlässt) , muss den verbleibenden Patienten etwas passieren. Eine Möglichkeit ist, dass sie gelöscht werden. Ein weiterer Grund ist, dass ein Standardwert die Dokumentreferenz ersetzt oder sie aus der Haupttabelle entfernt und an einer anderen Stelle platziert werden können. Alternativ tritt keine Aktivität auf und die Patienten bleiben unberührt, als ob der Arzt noch anwesend wäre. Es kommt darauf an, was Sie tun möchten.

Denken Sie aus persönlicher Erfahrung sorgfältig über das Design der Datenbank nach. Diese Woche musste ich eine Bereinigung verwaister Aufzeichnungen in einer Tabelle durchführen, die auf nichts hinwies und buchstäblich Platz beanspruchte.


Ich muss die untergeordneten Datensätze löschen, wenn der übergeordnete Datensatz gelöscht wird.
Ramesh

Wenn die Aufzeichnungen vollständig gelöscht werden müssen und es nicht sinnvoll ist, sie zu behalten, ist ein kaskadierendes Löschen in Ihrer Situation
sinnvoller

3

Die Verwendung des kaskadierenden Löschens ist eine Frage der persönlichen Präferenz, z. B. ob Tabellen mit mehreren Namen benannt werden sollen oder nicht (Kunde gegen Kunden).

Ich würde es vorziehen, niemals kaskadierendes Löschen zu verwenden. Einige Datenbankdesigns vermeiden das Löschen überhaupt. Es gibt nur wenige Gründe, Daten aus einer Datenbank zu löschen, wenn der Speicherplatz so billig ist. Einige Datenbankdesigns setzen ein zusätzliches Feld "IsDeleted", anstatt Daten physisch zu löschen.

Wenn Sie Daten löschen müssen, erhalten Sie durch die Verwendung gespeicherter Prozeduren mehr Transparenz und Kontrolle. Ihre Anwendung kann eine gespeicherte Prozedur ausführen, die vom untergeordneten und dann vom übergeordneten Element gelöscht wird. Sie wissen nicht, wie sich die Geschäftsanforderungen im Laufe der Zeit ändern werden, sodass sp's Ihnen mehr Vielseitigkeit bieten. Das ist mein 2c.


Es gibt Ihnen zwar mehr Vielseitigkeit, führt aber auch "verstecktes" Verhalten ein, was bedeutet, dass Sie zusätzliche Dokumentation für diese SPs benötigen (damit die Benutzer wissen, welche Geschäftsaktion welche SP erfordert). Eine andere Möglichkeit besteht darin, SQL-Benutzer darauf zu beschränken, nur zu sein in der Lage, diese SPs auszuführen und überhaupt keine anderen "einfachen" Einfügungen / Aktualisierungen auszuführen.
DrCopyPaste
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.