有人可以告诉我如何在模式触发器中找到新旧值之间的差异吗?
触发器在INSERT
,UPDATE
,DELETE
上运行。我知道trgigger可以使用:old.*
和:new.*
答案 0 :(得分:4)
我认为你的意思是你有一个行级触发器,而不是一个模式级别的触发器。例如,某人在架构中的表上执行DDL时会触发架构级触发器。在谈论模式级别的触发器时,谈论新旧值是没有意义的。
如果我们讨论的是行级触发器,我认为你只对UPDATE
语句感兴趣。如果要插入或删除数据,则自然会更改表格中的每一列。
因此,如果我们讨论在UPDATE
上触发的行级触发器,则可以使用UPDATING
函数。这告诉您是否正在更新特定列。但是,它并不一定告诉您数据正在被更改。声明
UPDATE table_name
SET col1 = col1;
为COL1
中的每一行更新TABLE_NAME
,但实际上并未更改任何数据。如果这是可以接受的,你可以做类似
CREATE TRIGGER trg_table_name
BEFORE UPDATE ON table_name
FOR EACH ROW
BEGIN
IF( updating( 'COL1' ) )
THEN
<<col1 was updated>>
END IF;
IF( updating( 'COL2' ) )
THEN
<<col2 was updated>>
END IF;
...
END;
你可以通过循环USER_TAB_COLS
中的数据来使动态更加动态,即
SQL> ed
Wrote file afiedt.buf
1 create table foo (
2 col1 number,
3 col2 number,
4 col3 number
5* )
SQL> /
Table created.
SQL> create trigger trg_foo
2 before update on foo
3 for each row
4 begin
5 for cols in (select *
6 from user_tab_cols
7 where table_name = 'FOO')
8 loop
9 if updating( cols.column_name )
10 then
11 dbms_output.put_line( 'Updated ' || cols.column_name );
12 end if;
13 end loop;
14 end;
15 /
Trigger created.
SQL> set serveroutput on;
SQL> insert into foo values( 1, 2, 3 );
1 row created.
SQL> update foo
2 set col2 = col2 + 1,
3 col3 = col3 * 2;
Updated COL2
Updated COL3
1 row updated.
虽然这可以显示所有正在更新的列,但主要的缺点是无法以类似的动态方式访问:new
和:old
值。因此,您可以发现COL2
已更新,但您无法确定:new.col2
或:old.col2
值的内容,而无需静态引用这些值。
潜在地,根据您尝试解决的问题,您可以编写动态生成触发器的代码,方法是查看数据中的数据。此块的某些内容将生成一个特定表的触发器,该表打印出所有:new
值
DECLARE
l_tbl_name VARCHAR2(100) := 'FOO';
l_sql_stmt VARCHAR2(4000);
BEGIN
l_sql_stmt := 'CREATE OR REPLACE TRIGGER trg_' || l_tbl_name ||
' BEFORE UPDATE ON ' || l_tbl_name ||
' FOR EACH ROW ' ||
'BEGIN ';
FOR cols IN (SELECT *
FROM user_tab_cols
WHERE table_name = l_tbl_name )
LOOP
l_sql_stmt := l_sql_stmt ||
' IF UPDATING( ''' || cols.column_name || ''' ) ' ||
' THEN ' ||
' dbms_output.put_line( :new.' || cols.column_name || '); ' ||
' END IF; ';
END LOOP;
l_sql_stmt := l_sql_stmt || ' END; ';
dbms_output.put_line( l_sql_stmt );
EXECUTE IMMEDIATE l_sql_stmt;
END;
答案 1 :(得分:2)
:old :new
=======================================================
insert | null | new value to be inserted
update | old value | new value to be updated
delete | old value | null
=======================================================
以上值是参考行级触发器引用的,这意味着每次触发都会触发每行。
上表显示了相对于上述dml语句的new old值,让我们举个例子。
Insert into abc (1,'gaurav soni',pune);--empid,name,city
假设我在表abc上有一个触发器,当插入表abc时,检查该位置表中是否存在该城市(我知道我们可以使用外键约束来执行此操作)但这是一个示例,所以我们可以将城市称为:new.city
,但我们无法在插入时引用:old .city
,因为其值为null
。
如果是update
,我们可以同时引用:new and :old value
如果delete
old value
,new value
只能引用null
deleting
:new
delete
。
注意:在:old
的情况下使用inserting
,compile time error
run time error
的{{1}}将不会为您INSERTING,DELETING
,但肯定会繁荣并给你{{1}}
您可以使用{{1}}子句来避免这种情况。