Skip to main content

One row only

Im Laufe der Zeit verwendet man in den erstellten Datenbanken verschiedene technische Prinzipien zum Aufbau und Design von Tabellen. Manche davon, selbst wenn eher selten genutzt, kommen dabei trotzdem regelmäßig wieder zum Einsatz.

Ein "Feature", das ich immer wieder hilfreich finde: eine Tabelle, die genau einen Datensatz beinhaltet. Dabei muss sichergestellt werden, dass Clients diesen Datensatz nicht löschen können und auch keine weiteren Datensätze anlegen können.

Umsetzung

Anlegen der Tabelle

CREATE TABLE one_row_only (
    one_row_only INTEGER NOT NULL DEFAULT 1 CHECK ( one_row_only = 1 ) PRIMARY KEY,
    some_value TEXT NOT NULL
);

Der Primärschlüssel (hier one_row_only genannt):

  • nimmt Integer-Werte auf
  • darf nicht leer sein
  • der Standardwert, der eingetragen wird, ist die "1"
  • es wird geprüft, dass ausschließlich der Wert "1" eingetragen werden kann
  • uns es handelt sich eben um den PRIMARY KEY, d.h. es können keine doppelten Werte vorkommen

Damit ist sichergestellt, dass ausschließlich ein Datensatz in dieser Tabelle angelegt werden kann. Jetzt muss noch sichergestellt werden, dass dieser von den Clients nicht mehr gelöscht werden kann.

Anlegen des Triggers

PostgreSQL-Trigger bestehen immer aus zwei Bestandteilen:

  • einer Trigger-Funktion
  • und dem tatsächlichen Trigger, der bei Eintreten eines Sachverhalts diese Trigger-Funktion aufruft
CREATE FUNCTION prevent_deletion() RETURNS TRIGGER
LANGUAGE PLPGSQL
AS $$
BEGIN
  RAISE EXCEPTION 'Do not attempt to delete from one_row_only';
  RETURN NULL;
END;
$$

CREATE TRIGGER tdb_one_row_only BEFORE DELETE ON one_row_only
FOR EACH ROW
EXECUTE PROCEDURE prevent_deletion();

Die Trigger-Funktion wirft eine Exception und gibt anschließend NULL zurück. Das führt dazu, dass die Datensatz-Operation, die den Trigger ausgelöst hat, verworfen wird. In diesem Fall wird also das versuchte Löschen des Datensatzes abgebrochen. Da wir das vor dem Löschen des Datensatzes prüfen müssen, verwenden wir einen BEFORE DELETE-Trigger.

Datensatz anlegen und testen

INSERT INTO one_row_only VALUES ( DEFAULT, 'something' );
COMMIT;


SELECT * FROM one_row_only;

one_row_only|some_value|
------------+----------+
           1|something |


DELETE FROM one_row_only;

SQL-Fehler [P0001]: FEHLER: Do not attempt to delete from one_row_only
  Wobei: PL/pgSQL-Funktion prevent_deletion() Zeile 3 bei RAISE