Bedingung bei INSERT und UPDATE einhalten

Probleme und Fragen zum Thema Trigger und Funktionen.
Antworten
mia
Neuer Benutzer
Beiträge: 3
Registriert: Mo 29. Mai 2006, 13:25

Bedingung bei INSERT und UPDATE einhalten

Beitrag von mia »

Hallo,

ich möchte erreichen, daß bestimmte Einträge in einer Tabelle
festgelegte Bedingungen erfüllen und zwar sowohl bei INSERT als auch
bei UPDATE. Ich habe schon verschieden Möglichkeiten ausprobiert
(Trigger, Rules etc.) bis jetzt aber noch keine Lösung gefunden, bei
der beides funkioniert.

Hier kommt mein Beispiel:

Tabelle:

CREATE TABLE profil (
personid integer PRIMARY KEY,
patient boolean DEFAULT false,
untersucher boolean DEFAULT false,
operateur boolean DEFAULT false
);

jetzt ein paar Werte einfüllen:

insert into profil (1,f,t,f);
insert into profil (2,f,t,f);


Einer Person können bestimmte Profilmerkmale zugewiesen werden
(patient/ untersucher /arzt).

Bedingung: Jeder Operateur ist gleichzeitig ein Untersucher, aber nicht
jeder Untersucher ist immer ein Operateur


Variante 1)

CREATE RULE keepclean AS ON INSERT
TO profil WHERE NEW.operateur=true
DO (UPDATE profil SET untersucher = true where operateur=true);

-- funktioniert prima für alle INSERTS, natürlich nicht für UPDATE,
wenn ich dieselbe Regel für UPDATE erzeuge bekomme ich als
Fehlermeldung:

infinite recursion detected in rules for relation "profil"


also habe ich's mit einer Funktion versucht:

Variante 2)

CREATE FUNCTION profilupdate() RETURNS opaque AS '

BEGIN
IF TG_OP = ''INSERT'' THEN
UPDATE profil SET untersucher = true WHERE personid = NEW.personid;
END IF;
RETURN NEW;

END;
' LANGUAGE 'plpgsql';

CREATE TRIGGER profilupdate
AFTER INSERT OR UPDATE
ON profil FOR EACH ROW
EXECUTE PROCEDURE profilupdate();

-- INSERT funktioniert richtig, UPDATE ändert nur den Wert für operateur
nicht aber für untersucher



inzwischen habe ich x varianten probiert, stundenlang zig verschiede
Dokumentationen und Handbücher gelesen und komme einfach nicht
weiter....javascript:emoticon(' :o ops:')

Ich bin für jede Idee dankbar! Wahrscheinlich hab' ich eh nur ein riesiges Brett vorm Kopf...

Mia

fristo
Erfahrener Benutzer
Beiträge: 670
Registriert: Do 8. Dez 2005, 12:30
Wohnort: Raum Frankfurt/Main

Beitrag von fristo »

Hallo Mia,

folgender Vorschlag: Erstelle 2 Personentabellen, eine für die Patienten, die andere für die Ärzte. Ansonsten könntest Du ein Problem bekommen, wenn ein Arzt zum Patient wird.



Das Problem mit dem Profil würde ich wie folgt lösen:

Code: Alles auswählen

create          profil_arzt
                {
                id                      SERIAL,
                beschreibung            varchar
                };

insert profil_arzt (beschreibung) values ('operateur');
insert profil_arzt (beschreibung) values ('untersucher');
insert profil_arzt (beschreibung) values ('operateur + untersucher');


create          person_arzt
                {
                id                      SERIAL,
                name                    varchar,
                id_profil_arzt          integer REFERENCES profil_arzt
                };
               
insert person_arzt (name, id_profil_arzt) values ('aaa', 1);
insert person_arzt (name, id_profil_arzt) values ('bbb', 2);
insert person_arzt (name, id_profil_arzt) values ('ccc', 3)


Dies hat 2 Vorteile: Die Tabelle profil_arzt kann jederzeit erweitert werden. Durch die refenzielle Integrietät muss die Person Arzt immer ein Profil haben.



mfg

fristo

mia
Neuer Benutzer
Beiträge: 3
Registriert: Mo 29. Mai 2006, 13:25

Beitrag von mia »

hallo fristo,

danke für den Lösungsvorschlag. Muß mir das Ganze nochmal in Ruhe durchdenken, die gesamte Datenbankstruktur ist nämlich etwas komplexer als ich das in dem Beispiel beschrieben habe. (die Personen sind natürlich nur ein Teil des ganzen...)

Ich habe inzwischen folgendes versucht:

1. RULE für INSERT wie oben

Code: Alles auswählen

CREATE RULE check AS ON INSERT 
TO profil WHERE NEW.operateur=true
DO (UPDATE profil SET untersucher = true);



2. Dann zusätzlich eine Funktion, die nur NACH einem UPDATE ausgeführt werden soll:

Code: Alles auswählen

 CREATE FUNCTION profilupdate() RETURNS opaque AS '
   
   BEGIN
        IF TG_OP = ''UPDATE'' THEN
        UPDATE profil SET untersucher = true WHERE operateur = true;
     END IF;
   RETURN NEW;

    END;
 ' LANGUAGE 'plpgsql';
 
 CREATE TRIGGER profilupdate
                AFTER INSERT OR UPDATE
                ON profil FOR EACH ROW
                EXECUTE PROCEDURE profilupdate();


Hab's natürlich probiert... gibt eine wahnsinnige Verzögerung, es passiert nix und wenn ich dann abbreche:

Code: Alles auswählen

SQL statement "UPDATE profil SET untersucher = true WHERE operateur = true"
PL/pgSQL function "profilupdate" line 4 at SQL statement


Tja... Wisu denn bluus????

dachte es müßte doch ganz einfach sein, das Ganze zu automatiseren...
:?

noch eine schönen Abend,

Mia

fristo
Erfahrener Benutzer
Beiträge: 670
Registriert: Do 8. Dez 2005, 12:30
Wohnort: Raum Frankfurt/Main

Beitrag von fristo »

Hallo Mia,

mia hat geschrieben:Tja... Wisu denn bluus????

dachte es müßte doch ganz einfach sein, das Ganze zu automatiseren...

Hier fehlt Dir etwas Know How. Mit NEW bzw OLD kannst Du bei RULES und Triggerfunktion auf den aktuellen Datensatz zugreifen. Die genauen Details solltest Du in der Doku nachlesen.



Und wenn Du folgenden Code testet, sollte es auch funktionieren

[code]CREATE OR REPLACE FUNCTION check_profil(]
Ist doch ganz einfach! Oder?



PS: Syntaxfehler können vorhanden sein. Wurde nicht getestet!



mfg

fristo

mia
Neuer Benutzer
Beiträge: 3
Registriert: Mo 29. Mai 2006, 13:25

Beitrag von mia »

@ fristo

vielen herzlichen Dank!!! Konnte die Funktion mit kleineren Änderungen optimal nutzen! Klappt alles!! Habe übrigens schon vorher das NEW in eine Funktion eingebaut, war aber in diesem Fall immer am syntaktisch richtigen Aufbau der vollständigen Funktion gescheitert....wollte möglichst alle Einzelfälle in der Funktion regeln und habe mich dann hoffnungslos verstrickt... jetzt ist mir klar geworden, daß ich das ja viel eleganter über verschiedene Trigger lösen kann (z.B. je einen für UPDATE und INSERT).

Dein Tip war also auch mental bahnbrechend und ich konnte gleich noch eine ganze Reihe anderer Probleme lösen javascript:emoticon(':lol:')

Wie immer sind also die einfachen Dinge doch die besten (und die alte Weisheit, Frauen würden Dinge gern unnötig kompliziert gestalten trifft zumindestens in diesem Fall auf mich zu...)

Noch einmal ganz herzlichen Dank!



Mia

fristo
Erfahrener Benutzer
Beiträge: 670
Registriert: Do 8. Dez 2005, 12:30
Wohnort: Raum Frankfurt/Main

Beitrag von fristo »

Hallo Mia,

mia hat geschrieben:Wie immer sind also die einfachen Dinge doch die besten (und die alte Weisheit, Frauen würden Dinge gern unnötig kompliziert gestalten trifft zumindestens in diesem Fall auf mich zu...)

Stell Dich nicht so negative dar. Das passiert jedem mal. So etwas nennt man dann Betriebsblindheit. Dann helfen nur noch zwei Dinge, Sachen packen, nach Hause gehen und eine Nacht darüber schlafen oder jemand anderes fragen. Hat doch geholfen.



mfg

fristo

Antworten