Wie implementiere ich Soft Deletes?

7

Wie implementieren Sie weiche Löschvorgänge in einer Datenbank?

Idealerweise würde die Lösung dies ermöglichen

  • anständige Leistung auf großen Tischen
  • Beziehungen berücksichtigen
  • Berücksichtigen Sie eindeutige Schlüssel
  • Der Benutzer sollte in der Lage sein, seine gelöschten Elemente zu finden und wiederherzustellen.

Vielen Dank!

Neil McGuigan
quelle

Antworten:

6

Ich kann mir verschiedene Möglichkeiten vorstellen, dies zu tun:

  • Möglicherweise haben Sie die Anzeige "Gelöscht", die beim Löschen eines Datensatzes auf "Y" gesetzt wird. Sehr einfach, aber es werden gelöschte und aktive Daten in denselben Tabellen belassen, was bei viel Aktivität zu Leistungsproblemen führen kann. Das Wiederherstellen eines Datensatzes ist so einfach wie das Ändern des Indikators.

  • Sie könnten eine Tabelle haben, die die Struktur der Tabelle widerspiegelt, aus der Sie löschen möchten. Wenn Sie einen Datensatz aus der Haupttabelle löschen, fügen Sie diesen Datensatz in die Tabelle "deleted_data" ein. Auf diese Weise können Sie gelöschte Daten in eine separate Tabelle verschieben, um der Haupttabelle eine bessere potenzielle Leistung zu bieten. Die Suche nach Daten in beiden Tabellen kann jedoch die Sache komplizierter machen, und die Synchronisierung der Datenstrukturen (wenn sie sich ändern) ist ebenfalls ein wenig mehr Arbeit, die getan werden muss. In diesem Fall müsste zum Wiederherstellen der Daten der Datensatz aus der "gelöschten" Tabelle entfernt und wieder in die Haupttabelle eingefügt werden.

In beiden Fällen möchten Sie möglicherweise untergeordnete Datensätze suchen und diese ebenfalls als gelöscht markieren. Ich nehme an, Sie könnten dies mit Triggern oder mit Code tun.

FrustratedWithFormsDesigner
quelle
Wie verhindern Sie bei Verwendung des Ansatzes eines gelöschten Flags einen versehentlichen Zugriff auf die weich gelöschten Zeilen?
Mark Stosberg
@MarkStosberg: Eine Möglichkeit wäre, dass die Anwendung, die die Daten liest, aus einer Ansicht lesen kann, die alle weich gelöschten Zeilen ausschließt.
FrustratedWithFormsDesigner
3

In diesem Beispiel verwenden wir eine Tabelle, die so aussieht: "

CREATE TABLE parent_data
(
    id int not null auto_increment,
    ...
    PRIMARY KEY (id)
);

Wenn Sie weiche Löschvorgänge ausführen möchten, erstellen Sie eine Tabelle, die die ID der zu löschenden Zeilen enthält. Vielleicht so etwas:

CREATE TABLE deleted_parent_data SELECT id FROM parent_data WHERE 1=2;
ALTER TABLE deleted_parent_data ADD PRIMARY KEY (id);

Angenommen, Sie möchten die Zeilen 10, 20, 30, 40, 50 löschen. Führen Sie einfach Folgendes aus:

INSERT IGNORE INTO deleted_parent_data VALUES (10),(20),(30),(40),(50);

Sie müssten immer INNER JOINs ausführen, um gültige Daten zu sehen

SELECT A.* FROM parent_data A
INNER JOIN deleted_parent_data B
USING (id) WHERE B.id IS NULL;

Gelöschte Zeilen zu sehen wäre sehr schnell

SELECT B.* FROM deleted_parent_data A
LEFT JOIN parent_data B
USING (id) WHERE B.id IS NOT NULL;

Um Zeile 20 in parent_data wiederherzustellen, führen Sie einfach aus

DELETE FROM deleted_parent_data WHERE id = 20;

Um die Zeilen 20 und 50 dauerhaft zu löschen, führen Sie zwei Schritte aus, die Sie nicht zurücksetzen können:

DELETE B.* FROM
(SELECT id FROM deleted_parent_data
WHERE id IN (20,50)) A
LEFT JOIN parent_data B
USING (id) WHERE B.id IS NOT NULL;
DELETE FROM deleted_parent_data WHERE id IN (20,50);

Wenn die Tabelle child_data untergeordnete Datensätze enthält, müssen Sie eine separate Tabelle delete_child_data haben und diese auf ähnliche Weise verwalten. Vielleicht sieht der Tisch so aus:

CREATE TABLE deleted_child_table SELECT parent_id,id WHERE 1=2;
ALTER TABLE deleted_child_table ADD PRIMARY KEY (id);
ALTER TABLE deleted_child_table ADD UNIQUE KEY (parent_id,id);

Sie könnten wahrscheinlich Trigger oder FOREIGN KEY-Einschränkungen zwischen deleted_parent_table und deleted_child_table mit allen Schnickschnack verwenden ON DELETE CASCADE. Auf diese Weise sollte ein dauerhaftes Löschen der Zeile in deleted_parent_table zu deleted_child_table kaskadieren.

RolandoMySQLDBA
quelle