PDA

View Full Version : SQL-Trigger



Seiten : [1] 2

loeweadolf
30-12-05, 14:05
Ein SQL-Trigger kann z.B. ausgelöst werden nach Änderunge eines bestimten Feldes in einer Datei.

Beispiel: create Trigger lib/name after update of Feld1 on lib/Datei

Jetzt würde ich gerne den Trigger auslösen, wenn eines von 3 Feldern geändert wurde. Kann man mit OR arbeiten ? oder ähnliches, oder ist für jedes Feld ein eigener Trigger zu erstellen ?


Ludger

B.Hauser
30-12-05, 14:29
Hallo Ludger,

versuch mal folgendes:


CREATE TRIGGER MySchema/MyTable
AFTER UPDATE OF Fld1, Fld2, Fld3 on MyTable


Birgitta

loeweadolf
30-12-05, 18:14
Hallo Birgitta, da klappt ja wunderbar.

Ich habe aber noch ein anderes Problem. Ich habe versucht, aus Deiner Beschreibung: "Welches Programm aktivierte meinen Trigger ?" das auslösende Programm zu ermitteln.
Dabei wird mir aber folgende Fehlermeldung angezeigt:



Routine TRIWERCL in MUHSTANPGM mit angegebenen Parametern nicht gefunden.
SQL-Auslöser TR_LAGBES2 in ANCRAPGM ist mit SQLCODE -440 SQLSTATE 42884
fehlgeschlagen.
Fehler im Auslöserprogramm.
Fehler im Auslöserprogramm.


Ich habe folgendes CL erstellt und compiliert:


/************************************************** ***************/
/* T R I W E R C L / compiliert nach MUHSTANPGM */
/* welches Programm löste das Trigger-Programm aus ? */
/* Author . . . . . . . . : B.Hauser */
/************************************************** ***************/

PGM PARM(&CALLER +
&CALLED)
/* ---------------------------------------------------------------*/
DCL VAR(&CALLER) TYPE(*CHAR) LEN(10)
DCL VAR(&CALLED) TYPE(*CHAR) LEN(10)

DCL VAR(&MSGKEY) TYPE(*CHAR) LEN(4)
DCL VAR(&SENDER) TYPE(*CHAR) LEN(80)
/* ---------------------------------------------------------------*/
SNDPGMMSG MSG('TEST') +
TOPGMQ(*PRV (&CALLED)) +
MSGTYPE(*RQS) +
KEYVAR(&MSGKEY)

RCVMSG PGMQ(*PRV (&CALLED)) +
MSGKEY(&MSGKEY) +
SENDER(&SENDER)

CHGVAR VAR(&CALLER) VALUE(%SST(&SENDER 56 10))
ENDE: ENDPGM




Folgende Stored-Procedure habe ich erstellt und mit RUNSQLSTM erstellt



CREATE PROCEDURE MUHSTANPGM/TRIWERPC (
OUT ParmCaller CHAR(10) ,
IN ParmCalled CHAR(10) )
LANGUAGE CL
SPECIFIC MUHSTANPGM/TRIWERPC
NOT DETERMINISTIC
NO SQL
CALLED ON NULL INPUT
EXTERNAL NAME 'MUHSTANPGM/TRIWERCL'
PARAMETER STYLE SQL ;



Der Trigger sieht folgendermassen aus:




CREATE TRIGGER ancrapgm/tr_lagbes2
AFTER UPDATE OF LAPROS, LALORT ON lagbespf
REFERENCING NEW ROW AS neu
OLD ROW AS alt
FOR EACH ROW MODE DB2ROW

BEGIN
DECLARE I_pgm CHAR(10) default 'QDBUDR';
DECLARE O_pgm CHAR(10) default ' ';
DECLARE A_QUAL CHAR(6);
DECLARE B_QUAL CHAR(6);
SET A_QUAL = substring(alt.laarti, 1, 6);
SET B_QUAL = substring(neu.laarti, 1, 6);

call MUHSTANPGM/TRIWERPC(O_pgm, I_pgm);

INSERT into ancradta/LATRIGpf
(LWFIRM,
LWstkn,
LWprgr,
LWvkg1,
LWpros,
LWlort,
LWnmen,
LWvgre12,
LWqual,
LWvere,
LWDESS,
LWPROGRA)
values(
neu.LaFIRM,
neu.Lastkn,
neu.Laprgr,
neu.Lavkg1,
neu.Lapros,
neu.Lalort,
neu.Lanmen,
neu.Lavgre12,
B_qual,
neu.Lavere,
neu.LaDESS,
O_PGM) ;

end


Sobald ich die Anweisung: CALL MUHSTANPGM/TRIWERPC weglasse, funktioniert es, allerdings natürlich ohne die Ermittlung des Programm-Namens.


( TRIWERCL ist als Objekt in MUHSTANPGM vorhanden )



Was mache ich falsch ?

Ludger

Fuerchau
01-01-06, 15:27
PARAMETER STYLE SQL

ist wohl das Problem, da mehr als 2 Paramter an das CLP übergeben werden. Nimm die richtige Parameterdefinition.

loeweadolf
02-01-06, 11:59
PARAMETER STYLE SQL

ist wohl das Problem, da mehr als 2 Paramter an das CLP übergeben werden. Nimm die richtige Parameterdefinition.

Hallo Baldur,

ich habe die Stored Procedure geändert auf
PARAMETR STYLE GENERAL

Jetzt klappt es, ohne Abbruch (ich weiss aber nicht warum)

@Birgitta
Als Programm-Name wird bei DFU ermittelt: QDZXDBI (unabhängig, ob der Satz neu ist, geändert wird oder gelöscht wird. -> unterschiedliche Trigger)

In einem RPG-Programm mit embedded-SQL wird als programm-Name ermittelt bei update: QSQRUN3 .

Kann bei RPG evtl. auch der RPG-Name ermittelt werden ?
Gibt es weiterhin eine Möglchkeit, zu ermitteln, welcher Benutzer die Daten-Änderung vorgenommen hat ?

mfg. Ludger

kuempi von stein
02-01-06, 12:20
Hello,

Da gibts ja noch zig andere Möglichkeiten, wie Sätze reinkommen/verändert werden.
Als da wäre CPYF , RESTORE usw. usf.
Und die Java-Fraktion hatte damals einen gemeinsamen Account, da war eine Unterscheidugn auch schlecht.
Ich hatte früher auch mal das Problem, je nach Verursacher im Trigger entscheiden zu müssen...
Wenn ich mich richtig entsinne, hat es nie vollständig geklappt. Irgendwo ist immer der Wurm drin bzw. findet ein Anwender/Programm einen neuen unbekannten Weg.

Letzten Endes ist eine organisatorische Lösung aus meiner Sicht besser als diese Triggerei für Alle..

kuempi

loeweadolf
02-01-06, 12:33
Hello,

Da gibts ja noch zig andere Möglichkeiten, wie Sätze reinkommen/verändert werden.
Als da wäre CPYF , RESTORE usw. usf.
Und die Java-Fraktion hatte damals einen gemeinsamen Account, da war eine Unterscheidugn auch schlecht.
Ich hatte früher auch mal das Problem, je nach Verursacher im Trigger entscheiden zu müssen...
Wenn ich mich richtig entsinne, hat es nie vollständig geklappt. Irgendwo ist immer der Wurm drin bzw. findet ein Anwender/Programm einen neuen unbekannten Weg.

Letzten Endes ist eine organisatorische Lösung aus meiner Sicht besser als diese Triggerei für Alle..

kuempi

hallo kuempi,

ich arbeite eigentlich auch lieber mit durch von Anwendern ausgelösten Programme, die Protokolle schreiben. Dann hat man es wenigstens in der Hand, was passieren soll.

In diesem Falle lässt es sich aber nicht umgehen, Programme durch Datenbank-Aktivitäten anzustossen, da im Laufe von Jahren viele selbstgestrickte Progrämmchen entstanden sind. Da erscheint es als ersten Schritt zunächst mal einfacher: Unstimmigkeiten in den Daten über diesen Weg (Trigger) zu erkennen.

( es handelt sich um die am häufigsten und vielseitigsten genutzte Datei beim
Anwender )

mfg Ludger

B.Hauser
02-01-06, 13:59
Kann bei RPG evtl. auch der RPG-Name ermittelt werden ?


Das ist relativ einfach. Mit dem CL-Programm kannst Du Dich durch den kompletten Call-Stack hangeln. Einfach immer das ermittelte rufende Programm als aufgerufenes Programm übergeben. Das wird solange ausgeführt, bis Du den ersten Eintrag findest, der nicht mit Q anfängt. (Wenn Deine Programm-Namen allerdings mit Q anfangen hast Du verloren!)

Falls Du auch noch Modul und Prozedur ermitteln willst, musst Du die entsprechenden Informationen im SNDPGMMSG bei TOMSGQ angeben. Das rufende Modul wird im Sender ab Stelle 355 ausgegeben und die rufende Prozedur ab Stelle 375.

Alternativ kannst Du natürlich auch den CALL-Stack über das API QWVRCSTK (Retrieve Call Stack).

Birgitta

Fuerchau
02-01-06, 18:09
Wenn du eine Datei journalisierst, stehen Programm, User und Zeitmarke im Journal.
Ansonsten per RPG in der SDS den *USER-Eintrag oder per RTVJOBA den User abfragen.

Und was den Parameterstyle angeht:
Bei SQL werden noch NULL-Flag-Zeiger und eine Status-Area übergeben, bei General eben nur die Parameter.

loeweadolf
03-01-06, 01:06
Das CL habe ich erweitert um die Ermitteln des Users. Die Stored Procedure habe ich ergänzt um einen weiteren OUT-Parameter für ds obige CL für den User. Das klappt wohl.



Das ist relativ einfach. Mit dem CL-Programm kannst Du Dich durch den kompletten Call-Stack hangeln. Einfach immer das ermittelte rufende Programm als aufgerufenes Programm übergeben. Das wird solange ausgeführt, bis Du den ersten Eintrag findest, der nicht mit Q anfängt. (Wenn Deine Programm-Namen allerdings mit Q anfangen hast Du verloren!)


Ich habe das so verstannden, dass ich eine Schleife in das CL einbauen kann, die solange durchlaufen wird, bis der ermittelte Aufruf-Name nicht mehr mit -Q- anfängt.

Den Wert aus &CALLER bringe ich dann nach &CALLED und wiederhole das SNDPGMMSG.

Bei der ersten Wiederholung des SNDPGMMSG kommt allerdings folgende Fehlermeldung:



Job 060880/LUMU/LUMU_A im Subsystem QINTER in QSYS am 03.01.06 um 01:52:11 g
Nachrichtenwarteschlange LUDGER ist anderem Job zugeordnet.
CPF2469 von TRIWERCL bei 2600 empfangen. (C D I R)

Weitere Nachrichteninformationen

Nachrichten-ID . . . . : CPA0701 Bewertung . . . . . . : 99
Nachrichtenart . . . . : Anfrage
Sendedatum . . . . . . : 03.01.06 Sendezeit . . . . . . : 01:53:26

Nachricht . . . : CPF2469 von TRIWERCL bei 2600 empfangen. (C D I R)
Ursache . . . . . : Das CL-Programm TRIWERCL in Bibliothek MUHSTANPGM hat
einen Fehler bei Anweisung 2600 erkannt. Der Nachrichtentext für CPF2469
ist: Fehler aufgetreten beim Senden der Nachricht ..



Was könnte die Ursache sein ?