Ich suchte nach meinem Problem, konnte aber noch keine Lösung bekommen, also poste ich es hier. Ich verwende Oracle Database 12c Enterprise Edition Version 12.1.0.1.0 - 64-Bit-Produktion.Wie bekomme ich alte Werte in Compound Trigger Update in Oracle
Ich habe eine Main_Table mit annehmen 10 Datensätze und ich habe eine Log_Table, um die alten und neuen Werte bei der Aktualisierung der neuen Tabelle zu protokollieren (einzufügen).
Ich verwende einen Compound-Trigger (um Mutationsfehler zu vermeiden), um alle Spalten von "Main_Table" dynamisch zu durchlaufen und die aktualisierenden Zeileneinträge durch Filtern durch neue zu erhalten. Primärschlüssel (UID)).
Ich hoffe, ich verwende Compound Trigger richtig.
Ich verwende nicht :old
und :new
, da ich alle Spalten dynamisch durchlaufen muss und die Spaltenwerte übereinstimmen muss.
But it is again giving me mutating error:
Error report -
SQL Error: ORA-04091: table Main_Table is mutating, trigger/function may not see it
ORA-06512: at "Schema.TRG_TEST", line 87
ORA-04088: error during execution of trigger 'Schema.TRG_TEST'
04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.
Below is my trigger code:
create or replace TRIGGER TRG_TEST
FOR INSERT or UPDATE ON Main_Table
COMPOUND TRIGGER
TYPE NUMBER_TABLE IS TABLE OF NUMBER;
tblTABLE2_IDS NUMBER_TABLE;
TYPE VARCHAR_TABLE IS TABLE OF VARCHAR(2000);
tblTABLE3_IDS VARCHAR_TABLE;
TYPE VARCHAR_TABLE1 IS TABLE OF VARCHAR(2000);
tblTABLE4_IDS VARCHAR_TABLE1;
vcount NUMBER;
colCount NUMBER;
colCountAfter NUMBER;
vvalue VARCHAR2(4000);
vcolumn VARCHAR2(4000);
sql1 VARCHAR2(4000);
dynamicq varchar(4000);
testv varchar(2000);
testv1 varchar(2000);
ssql varchar(2000);
ssql1 varchar(2000);
maxsiteid NUMBER;
newsid varchar(2000);
newstid varchar(2000);
newuid varchar(2000);
--Executed before DML statement
BEFORE STATEMENT IS
BEGIN
tblTABLE2_IDS := NUMBER_TABLE();
tblTABLE3_IDS:= VARCHAR_TABLE();
tblTABLE4_IDS:= VARCHAR_TABLE1();
IF UPDATING THEN
dbms_output.put_line('Before Statement - In Updating');
--dbms_output.put_line('Before Each Row - In Updating');
-- tblTABLE2_IDS.EXTEND;
--tblTABLE2_IDS(tblTABLE2_IDS.LAST) := :new.UID;
END IF;
END BEFORE STATEMENT;
--Executed before each row change- :NEW, :OLD are available
BEFORE EACH ROW IS
BEGIN
IF UPDATING THEN
dbms_output.put_line('Before Each Row - In Updating');
tblTABLE2_IDS.EXTEND;
tblTABLE2_IDS(tblTABLE2_IDS.LAST) := :new.UID;
-- FOR columnlist IN
--(SELECT COLUMN_NAME AS COLUMN_NAME FROM all_tab_columns WHERE lower(TABLE_NAME) = 'Main_Table'
-- AND lower(COLUMN_NAME) NOT IN ('s_id' ,'msid' ,'st' ,'u_id' ,'db_flag'))
--LOOP
--colCount:=colCount+1;
--ssql1:='select '||columnlist.COLUMN_NAME||' from Main_Table where UID='||tblTABLE2_IDS(tblTABLE2_IDS.LAST)||'';
--dbms_output.put_line(ssql1);
--execute immediate ssql1 into testv;
--tblTABLE3_IDS(colCount):=testv;
--dbms_output.put_line(testv);
--END LOOP;
END IF;
END BEFORE EACH ROW;
--Executed aftereach row change- :NEW, :OLD are available
AFTER EACH ROW IS
BEGIN
IF UPDATING THEN
dbms_output.put_line('After Each Row - In Updating');
FOR columnlist IN
(SELECT COLUMN_NAME AS COLUMN_NAME FROM all_tab_columns WHERE lower(TABLE_NAME) = 'Main_Table'
AND lower(COLUMN_NAME) NOT IN ('s_id' ,'msid' ,'st' ,'u_id' ,'db_flag'))
LOOP
colCount:=colCount+1;
ssql1:='select '||columnlist.COLUMN_NAME||' from Main_Table where UID='||tblTABLE2_IDS(tblTABLE2_IDS.LAST)||'';
dbms_output.put_line(ssql1);
execute immediate ssql1 into testv;
tblTABLE3_IDS(colCount):=testv;
dbms_output.put_line(testv);
END LOOP;
END IF;
END AFTER EACH ROW;
--Executed after DML statement
AFTER STATEMENT IS
BEGIN
IF UPDATING THEN
dbms_output.put_line('After Statement - In Updating');
FOR columnlist IN
(SELECT COLUMN_NAME AS COLUMN_NAME FROM all_tab_columns WHERE lower(TABLE_NAME) = 'Main_Table'
AND lower(COLUMN_NAME) NOT IN ('s_id' ,'msid' ,'st' ,'u_id' ,'db_flag'))
LOOP
colCountAfter:=colCountAfter+1;
dbms_output.put_line('loop started');
ssql1:='select '||columnlist.COLUMN_NAME||' from Main_Table where UID='||tblTABLE2_IDS(tblTABLE2_IDS.LAST)||'';
execute immediate ssql1 into testv1;
dbms_output.put_line(testv);
tblTABLE3_IDS(colCountAfter):=testv1;
IF ((testv) IS NOT NULL) THEN
FOR i IN tblTABLE3_IDS.FIRST..tblTABLE2_IDS.LAST LOOP
dbms_output.put_line('Values No :' ||i||' is ' || tblTABLE3_IDS(i) || ' and ' ||tblTABLE4_IDS(i));
IF(tblTABLE3_IDS(i)=tblTABLE4_IDS(i)) THEN
dbms_output.put_line(testv1);
ELSE
-- dbms_output.put_line('select :new.'|| columnlist.COLUMN_NAME||' from dual');
dbms_output.put_line(testv1);
INSERT INTO Log_Table
(
user_id,
log_action,
log_table_name,
schema_name,
log_column_name,
col_old_val,
col_new_val,
ne_type,
ne_id,
system_id
)
VALUES
(
newuid,
'UPDATE',
'Main_Table',
'SCHEMA'
,columnlist.COLUMN_NAME
,tblTABLE3_IDS(i)
,tblTABLE4_IDS(i)
,'S'
,newstid
,newsid
);
END IF;
END LOOP;
END IF;
END LOOP;
END IF;
END AFTER STATEMENT;
END TRG_TEST;
Anfangs habe ich versucht hatte, in die Aktualisierung Tabelle zugreifen „Vor jeder Zeile“ dann habe ich versucht, es in „Nach jeder Zeile“, gleichen Fehler in beiden Fällen erreichbar.
Ich habe Mühe, eine Lösung zu finden, auch nach der Verwendung von Compound-Trigger, aber ich habe das gleiche für den Einsatz erreicht.
Kann jemand helfen, wie man es erreicht. Danke im Voraus.
Bitte veröffentlichen Sie die Datenbankversion und -version. Ich nehme an, du hast das Rad wiederbelebt. Es gibt einige Oracle-Produkte, die das gleiche tun. –
Ich verwende Oracle Database 12c Enterprise Edition Version 12.1.0.1.0 - 64-Bit-Produktion. – nks
Nein. Nur, nein. Diese Idee, dynamisches SQL * für jede einzelne DML-Anweisung zur Laufzeit zu erzeugen, zu kompilieren und auszuführen, ist wirklich schrecklich. Wenn Sie alle Änderungen mit einem Trigger verfolgen müssen, generieren Sie Ihren Triggercode für jede Tabelle einzeln. Sie werden sich eine Menge Schmerzen und Ärger ersparen, glauben Sie mir. –