Die Flexperten Herrlich & Ramuschkat

Datenbank: Logisches Löschen (“Soft Delete”) datenbankseitig umsetzen

Im aktuellen Projekt gibt es die Anforderung, dass Datensätze nicht physikalisch aus der Datenbank gelöscht werden dürfen, sondern lediglich als “gelöscht” markiert werden sollen.

Um das umzusetzen gibt es verschiedene Ansätze, in der Regel gibt es in den entsprechenden Tabellen eine “deleted” Spalte. Solange der Wert null ist, ist der Datensatz “da”, ist er != null, dann ist er “gelöscht”.

Bei wenigen SQL Abfragen kann man das zumeist manuell regeln, aber wenn man mal in einer WHERE Klausel vergessen hat, die Prüfung einzubauen, ist das schon doof. Schlimmer noch, wenn das Datenmodell komplexer ist, viele JOINS und Relationen im Spiel sind, noch schlimmer, wenn man Hibernate als Abstraktion zwischen DB und Objektmodell verwendet.

Eine sehr elegante Lösung ist daher, das Ganze über die Datenbank abzuwickeln. Der schöne Nebeneffekt dabei: es ist vollkommen transparent, d.h. man verwendet trotzdem DELETE Anweisungen und muss sich nicht um das weitere Handling kümmern (auch nicht beim SELECT!). Auch für Hibernate und andere Tools ist das entsprechend transparent.

Hier ein Beispiel für MS SQL Server (ab 2005), in Oracle müsste das ähnlich funktionieren.

In MS SQL kann man über die Trigger INSTEAD OF die SQL Anweisungen insert, update und delete “umleiten” bzw. beliebige andere Aktionen ausführen.

Darüber lässt sich auch das logisches Löschen von Datensätzen einfach implementieren. Dazu schreibt man einen INSTEAD OF DELETE Trigger, der anstelle eines DELETE dann z.B. ein UPDATE auf den entsprechenden Datensatz macht und ihn als gelöscht markiert.

Über entsprechende Views kann man dann wiederum verhindern, dass als gelöscht markierte Datensätze aus der Datenbank geholt werden. Hier ein Beispiel:

-- Tabelle person erstellen
CREATE TABLE person
(
id         int PRIMARY KEY,
name       nvarchar(100),
deleted    datetime
)
go

-- View für person, in der nur "ungelöschte" Daten geholt werden
CREATE VIEW v_person AS
SELECT id, name, deleted
FROM person
WHERE deleted is null
go

-- 4 Datensätze, einer davon "gelöscht"
insert into person (id, name, deleted) values (1, 'A', null)
insert into person (id, name, deleted) values (2, 'B', null)
insert into person (id, name, deleted) values (3, 'C', null)
insert into person (id, name, deleted) values (4, 'D', getdate())
go

select * from person
go
-- 4 Zeilen, A-D

select * from v_person
go
-- 3 Zeilen, der "gelöschte" Datensatz D ist nicht dabei

-- INSTEAD OF DELETE trigger / delete in update ändern
CREATE TRIGGER trigperson ON person
INSTEAD OF DELETE AS
BEGIN
update person
set deleted = getdate()
where id in (select id from deleted)
END
go

-- jetzt kommt's
delete from person where id = 2 (B löschen)
go

select * from v_person
go
-- 2 Zeilen, A und C

select * from person
go
-- immer noch alle 4

drop table person
go

drop view v_person
go

Via E-Mail von Dirk

4 Kommentare

  1. the venus factor am 03. October 2014
  2. venus factor am 03. October 2014
  3. cruise control diet am 03. October 2014
  4. venus factor am 03. October 2014

    http://www.smftr.com/the venus factor reviews

Einen Kommentar schreiben