Löschen von Zeilen aus Tabelle in Abhängigkeit von Werten einer anderen Tabelle

Hallo

Ich habe folgendes Problem, welches mir Kopfzerbrechen bereitet.
Ich studiere Geographie und besch�ftige mich mit Massenbewegungen in der Natur. Wenn einfach mal ein St�ck Hang abrutscht zum Beispiel.
So eine Massenbewegung (umgangssprachlich Rutschung), kann aus mehreren Teilen bestehen.

Hier ist mal ein kleiner Ausschnitt aus der Tabelle:

[TABLE=“width: 500”]
[TR]
[TD]teil1_existiert
[/TD]
[TD]teil1_id
[/TD]
[TD]teil2_existiert
[/TD]
[TD]teil2_id
[/TD]
[TD]usw
[/TD]
[/TR]
[TR]
[TD]1
[/TD]
[TD]teil1_0001
[/TD]
[TD]0
[/TD]
[TD]NULL
[/TD]
[TD]…
[/TD]
[/TR]
[TR]
[TD]1
[/TD]
[TD]teil1_0002
[/TD]
[TD]1
[/TD]
[TD]teil2_0002
[/TD]
[TD]…
[/TD]
[/TR]
[/TABLE]

Dazu habe ich eine Funktion geschrieben:

CREATE FUNCTION scp_exists_fct ()
RETURNS trigger AS'
BEGIN
IF new.scp_exists = ''1'' THEN
new.lscarp = ''scp'' || lpad(new.lnumber::text,4,''0'');
INSERT INTO scarp (scpnom) VALUES (new.lscarp);
RETURN new;
ELSEIF new.scp_exists = ''0'' THEN
new.lscarp = NULL;
RETURN new;
END IF;
END;'
LANGUAGE 'plpgsql';

Der Trigger ist klar (triggert ON INSERT AND UPDATE)

Die Kennung lscarp wird auch gleichzeitig in eine andere Tabelle geschrieben, in der dann Eigenschaften von teil1 stehen. Ver�ndere ich jetzt den Eintrag teil1_existiert von ‘1’ auf ‘0’ (boolean) soll die ganze Zeile mit der Kennung lscarp in der anderen Tabelle wieder gel�scht werden. Und anders herum.

Das zweite Problem ist, dass die Funktion auch dann triggert wenn ich ein Update in einer anderen Spalte, der selben Tabelle mache, die nichts damit zu tun hat. Ich habe gesehen, dass man das eventuell mit diesen Exceptions – do nothing machen kann. Das habe ich aber nicht hinbekommen.

Bis dahin schon mal vielen Dank.

Gr��e Stefan

Was das jetzt eine Problembeschreibung?

Das zweite Problem ist, dass die Funktion auch dann triggert wenn ich ein Update in einer anderen Spalte, der selben Tabelle mache, die nichts damit zu tun hat. Ich habe gesehen, dass man das eventuell mit diesen Exceptions – do nothing machen kann. Das habe ich aber nicht hinbekommen.

Falscher Ansatz. Beim Anlegen des TRIGGERS kannst Du eine WHERE-Condition angeben In dieser kannst Du auf die Feldinhalte von OLD und NEW zugreifen. Sind diese gleich, so ändert sich diese Spalte nicht, in dem Fall wird der Trigger übergangen.


Andreas

Hallo

Danke für den Tip mit der WHEN-Condition.
Das andere Problem ist, das ich nicht weiß, wie ich die Funktion dazu bringe, dass sie die Kennung aus der anderen Tabelle löscht, wenn der Wert auf ‘0’ gesetzt wird in der Tabelle. Und er soll die komplette Zeile löschen.

Hier nochmal die erweiterte Funktion:

CREATE OR REPLACE FUNCTION scp_exists_fct ()
    RETURNS trigger AS'
        BEGIN
            IF new.scp_exists = ''1'' THEN
                new.lscarp = ''scp'' || lpad(new.lnumber::text,4,''0'');
                INSERT INTO scarp (scpnom) VALUES (new.lscarp);
                RETURN new;
            ELSEIF new.scp_exists = ''0'' THEN
                new.lscarp = NULL;
                DELETE FROM scarp USING landslide WHERE scp_exists=''0'';
                RETURN new;
            END IF;
        
        END;'

    LANGUAGE 'plpgsql';

So scheint das nicht zu funktionieren.

Grüße Stefan

Klingt nach einem TRIGGER, der das machen soll.

Btw.: lesbarere wird es, wenn Du Dollar-Quoting nutzt. Also … trigger AS $$ … und dann brauchst keine '-Orgien mehr zu veranstalten.

Andreas

Welchen Datentyp hat scp_exists eigentlich?

Wenn das ein numerischer Wert ist, dann sollten überhaupt keine Quotes (’) verwendet werden. (also z.B. if new.scp_exits = 1)

Noch besser wäre es dort eine “echte” boolean Spalte zu verwenden.

Hallo castorp,

column scp_exists ist vom Datentyp boolean.

@akretschmer: Die WHEN-condition im trigger gilt nur für ON UPDATE. So kann ich also die Funktion nicht ausführen lassen, wenn ein Wert eingetragen wird und dann später verändert wird.

Mir ist aufgefallen, dass wenn ich die Kennung, die in der Funktion erzeugt wird und dann in die andere Tabelle geschrieben wird, ja nur gesetzt werden kann, wenn keine NOT NULL CONSTRAINTS in der anderen Tabelle existieren. Entweder man kann das irgendwie umgehen oder ich muss mir nochmal über den Aufbau der DB Gedanken machen.

Grüße und Vielen Dank