DB-Trigger, mutirende Tabellen

sabinechrista

Grünschnabel
Hi,
ich habe hier ein trigger problem und vielleicht kann mir ja jemand einen tip geben.

Es sind zwei tabellen TBL=kopftabelle und DET=Kindtabelle.
TBL:
SCHL_DAT_RH_NR asc
SCHL_DAT_ORD asc
Y_AEND_ZAEHL
...

DET:
SCHL_DAT_RH_NR asc
SCHL_DAT_ORD asc
FOLGR_NR asc
ORD_NR asc
SCHLUESSEL
...

In der DET muß es immer einen Satz mit schlüssel = blank geben. dieser kann über eine dialoganwendung angelegt werden. Es werden die ord_nr 1-8 verwendet. ist nun kein blank-wert vorhaben, soll es einen "pseudo"- satz mit schluessel = blank und ord_nr = 9 geben. wird nun aber ein zweiter satz in DET mit schluessel = blank gecshrieben oder geupdatet, dann soll
der DET-Satz mit der ord_nr=9 wieder gelöscht werden. ungekehrt, wird ein satz mit svhluessel = blank gelöscht oder in schluessel ein wert gecshrieben, dann muß wieder ein "Pseudo"-Satz mit ord_nr = 9 ud schluessel 0 blank gecshrieben werden.

mein trigger sieht so aus:
SQL:
CREATE OR REPLACE TRIGGER TBL
  after update ON TBL
  FOR EACH ROW
DECLARE
 PRAGMA AUTONOMOUS_TRANSACTION;
 v_anzahl NUMBER(10);
 v_anzahl_9 NUMBER(10);
 v_anzahl_wert NUMBER(10);   
BEGIN
  SELECT COUNT(*) INTO v_anzahl
  FROM DET WHERE SCHL_DAT_RH_NR = :NEW.SCHL_DAT_RH_NR and SCHL_DAT_ORD = :NEW.SCHL_DAT_ORD
  and SCHLUESSEL = ' ';
    IF v_anzahl = 0 THEN
        INSERT INTO DET(SCHL_DAT_RH_NR,SCHL_DAT_ORD,SCHLUESSEL,FOLGE_NR,ORD_NR,BEZ15,EFFDT,EFF_STATUS)
        VALUES(:new.SCHL_DAT_RH_NR,:new.SCHL_DAT_ORD,' ',1,9,' ',null,' ');
        commit;
    else
    SELECT COUNT(*) INTO v_anzahl_9
    FROM DET WHERE SCHL_DAT_RH_NR = :NEW.SCHL_DAT_RH_NR and SCHL_DAT_ORD = :NEW.SCHL_DAT_ORD
    and SCHLUESSEL = ' ' and ord_nr = 9;
    SELECT COUNT(*) INTO v_anzahl_wert
    FROM DET WHERE SCHL_DAT_RH_NR = :NEW.SCHL_DAT_RH_NR and SCHL_DAT_ORD = :NEW.SCHL_DAT_ORD
    and SCHLUESSEL = ' ' and ord_nr <> 9;
    if v_anzahl_wert > 0 
     and v_anzahl_9 > 0 then
-- 9er-leersatz vorhanden + leerwerte satz vorhanden  => 9-er-leersatz löschen
      DELETE from DET WHERE SCHL_DAT_RH_NR = :new.SCHL_DAT_RH_NR and SCHL_DAT_ORD = :new.SCHL_DAT_ORD
      and SCHLUESSEL = ' ' and ORD_NR = 9;
      commit;
    END IF;
    end if;
END;


Auf die DET kann ich den trigger ja nicht legen, das sie selber geändret wird. Nun ist es so, dass in TBL ein Änderungszähler Y_AEND_ZAEHL fortgeschrieben wird wenn in DET eine Änderung stattfindet. Daher liegt der Trigger nun auf TBL.
Ich finde keine anderes event, von wo aus ich den trigger feuern könnte. leider wird dieser Zähler schon vor dem schreiebn auf DET verändert, so dass es nicht funktionierte. Erst hatte ich meinen Trigger ohne
PRAGMA AUTONOMOUS_TRANSACTION,
da bekam ich den Fehler: ..DET wird gerade geändert, Trigger/Funktion sieht dies möglicherweise nicht
Mit PRAGMA AUTONOMOUS_TRANSACTION kommt nun keine Oracle-fehler mehr aber der trigger tut nicht was er soll.
Gibt es noch eine andere Möglichkeit dieses Problem per Trigger zu lösen

Grüße, Sabine



Trigger/Funktion sieht dies möglicherweise nicht
 
Zuletzt bearbeitet von einem Moderator:
Als erstes sollten wir mal definieren mit was für einer Datenbank du arbeiten willst. MySQL, Oracle, MS SQL?

Und kannst du bitte dein Code formatiert in Tags setzen, damit es lesbar wird?
[code=sql]Dein Code[/code]
 
Zuletzt bearbeitet von einem Moderator:
Version? 9.x 10.x 11.x 12.x?

Das Trigggerverhalten hat sich leider zwischenzeitlich etwas geändert.

Willst du mit dem Trigger auf die Original oder geänderten Daten oder beide zugreifen? Beachte, dass der Trigger mit zur Transaction gehört, d.h. werden daten aus einer 2ten Verbindung geändert sieht der Trigger diese bis zum commit nicht.

Gruss
SK
 
Version 10.2

ich möchte auf die geänderten daten zugreifen. du hast wahrscheinlich recht, das das eine transaktion ist, bekomm eich die alten werte zu fassen, das ist mein problem. ich verwendet ja im trigger "PRAGMA AUTONOMOUS_TRANSACTION", da setze ich commit´s ab. Weißt Du wie sich das auf die Gesamt-transaktion verhält? habe das statement leider abgekupfert und finde keine gescheite beschreibung.
Gibt es denn einen triggerart, die ich nach dem comit feuern kann
 
naja es gibt kniffe für post-commit-trigger aber naja... eigentlich sollen Transactionen genau dieses Szenario verhindern.

Benötigst du die Daten wirklich direkt nach dem Update schon? Deine Beschreibung ist etwas kryptisch. Kannst du vielleicht noch die beteiligten Tabellen beschreiben und was du genau zu erreichen versuchst?
Das ist aber kein SAP/R3 System, oder? Weil diese "tollen" Tabellen/Spaltennamen bin ich eigentlich nur von denen gewohnt... weil da gibts noch ein paar andere Fallstrinke.

Gruss
SK
 
Zuletzt bearbeitet:
Hey SK,

ok, ich versuchs mal etwas besser.
SQL:
SQL> descr ps_ya_basis_tbl;
 Name                                      Null?    Typ
 ----------------------------------------- -------- ------------
 SCHL_DAT_RH_NR                            NOT NULL VARCHAR2(7)
 SCHL_DAT_ORD                              NOT NULL VARCHAR2(6)
 FOLGE_NR                                  NOT NULL NUMBER(3)
 Y_FKB_SA_USA                              NOT NULL VARCHAR2(4)
 BEZ25                                     NOT NULL VARCHAR2(25)
 Y_AEND_DT                                          DATE
 Y_AEND_ZAEHL                              NOT NULL NUMBER(3)

SQL> descr ps_ya_basis_det;
 Name                                      Null?    Typ
 ----------------------------------------- -------- ------------
 SCHL_DAT_RH_NR                            NOT NULL VARCHAR2(7)
 SCHL_DAT_ORD                              NOT NULL VARCHAR2(6)
 SCHLUESSEL                                NOT NULL VARCHAR2(9)
 FOLGE_NR                                  NOT NULL NUMBER(3)
 ORD_NR                                    NOT NULL NUMBER(2)
 EFFDT                                              DATE
 EFF_STATUS                                NOT NULL VARCHAR2(1)
 BEZ15                                     NOT NULL VARCHAR2(15)

Es handelt sich um Gültigkeitstabellen (lookups). In der tab ps_ya_basis_det stehen die eigentlichen werte drinn, im Feld schluessel. Es kann auch den wert " " (blank) geben. Das Feld Ordnungsnummer ist einfach ein schlüssel für die Tab und wird von 1-8 hochgezählt, das system stellt sicher dass es nur bis max. 8 geht, un dkennt auch nur diese. In der Tabelle ps_ya_basis_tbl stehen kopfinformationen (Vatertabelle), aber bei jeder Änderung in der Det-Tabelle wird das Änderungsdatum y_aend_dt und der Änderungszähler y_aend_zaehl hochgezählt.
Nun gibt es ein zweites System, das auch auf diese Tabellen zugreift. und dieses system braucht immer einen Eintrag in der Det-Tabelle mit SCHLUESSEL = " " (blank). Daher schreiben wir per Trigger einen Pseude-Leersatz mit ORD_NR = 9 (den ignoriert unsere Anwendung).
Wenn es aber einen Eintrag mit blank schon gibt bzw. eingefügt wird muß der Pseuso-Leersatz wieder verschwinden.
Das soll ein Trigger tun.
Noch eine Schwierigkeit wäre, dass das Update auf die TBL-Tabelle schon VOR dem auf die DET-Tabelle erfolgt.

kann man das verstehen?

Grüsse, sabine
 
Zuletzt bearbeitet von einem Moderator:
Jup vielen Dank. Okay das muss ich mir mal etwas durch den Kopf gehen lassen. Ich werde da mal 1,2 Versuche basteln müssen. Hast du noch 1,2 Testsätze damit ich das hier mal auf dem Cluster ausprobieren kann. Bin gerade so zwischen 2 "Notfällen" deswegen etwas wenig Zeit sorry.

Verstehe ich das richtig, dass eure Applikation so arbeitet:
Begin Transaction
...[deine SQL´s + Trigger]...
Commit;

Also es kommt kein weiteres Commit?

Führt eure Applikation ein automatisches Rollback? Also sendet sie bei einem Fehler das "Rollback" Kommando. Weil da gabs mal irgendwann einen Bug, dass Post-Commit Trigger dann nicht mehr "rückabgewickelt" wurden, was dann natürlich Tödlich wäre. Deswegen sind die auch irgendwann mal "verhindert" worden.

Gruss
SK

PS: Gib mir mal bitte Zeit bis morgen ;)
 
Zuletzt bearbeitet:
wow, echt nett das Du Dir das ansehen willst!
ja die application arbeitet so wie du schreibst. soweit ich weiß werden hier keine rollbacks abgesetzt.
Hier die Test-Daten:
SQL:
SQL> select * from ps_ya_basis_tbl where schl_dat_ord = '201088';
SCHL_DA SCHL_D   FOLGE_NR Y_FK BEZ25                     Y_AEND_D Y_AEND_ZAEHL
------- ------ ---------- ---- ------------------------- -------- ------------
00      201088          1 1920 Kostenstelle DAI60        09.02.10           72

SQL> select * from ps_ya_basis_det where schl_dat_ord = '201088';

SCHL_DA SCHL_D SCHLUESSE   FOLGE_NR     ORD_NR EFFDT    E BEZ15
------- ------ --------- ---------- ---------- -------- - ---------------
00      201088                    1          1            Leerwert KST
00      201088 A                  1          2            PS KST Abr.mon.
00      201088 F                  1          3            PS KST Zahlmon.
 
Zuletzt bearbeitet von einem Moderator:

Neue Beiträge

Zurück