触发器
trigger
数据库对象
命名块,有名字,会被编译并存储在数据库中
当在表、视图、数据库中发生某些事件时,Oracle会自动执行的一段程序
只有在触发器对应的事件发生时,触发器才会执行,触发器是自动执行的一段代码,用户不能调用
触发器的4要素:
1、触发源
用于指定在操作什么时会引发触发器执行
表、视图、数据库
2、触发的事件
用于指定在触发源上执行哪些操作会引发触发器执行
insert 、update 、delete、logon、logonoff
3、触发的时间
用于指定是在操作执行之前、之后,执行触发器
before after
4、触发的频率
用于指定在事件发生时,触发器执行几次
语句级 一条SQL语句,无论操作了几行,触发器只执行一次
行级 一条SQL语句,每操作1行,触发器就执行1次
1、DML触发器
创建语法:
create trigger 触发器名字
{before|after}
{insert|update|delete} on 表名
[for each row]
[when (条件)]
[declare
/*
*定义部分
*/
]
begin
/*
*触发体
*/
[exception
]
end;
for each row
用于指定是行级触发器
when (条件)
触发限制
只有when中指定的条件为true时,才会执行触发器
访问旧行、新行 new old 不需要加冒号
可以为一个触发器指定多个触发事件,多个事件之间通过or分隔
在触发器的底层管理了事务,内部事务?还是不太准确
所以自己写的触发器代码中,不允许写commit、rollback语句
对于DML、instead of触发器
与引发该触发器的DML操作,用的是同一个事务 执行DML操作时,打开的连接关联的事务
在DML触发器的执行过程中
如果发生了错误,会rollback,并会阻止后续操作的执行(before触发器,后面还要执行DML操作)
如果执行成功,不会commit
对于系统触发器
执行时,可能会执行DML操作
发生异常,回滚
成功,提交
例:
单表操作的before、after表级触发器,使用游标取表数据,验证在DML操作执行前后执行触发器
行级触发器的话,表 HWZ.T_EMP 发生了变化, 触发器/函数不能读它
下面例子:验证使用的是同一个事务,出错之后会回滚
create table t_emp_copy as select * from t_emp where 1 = 2;
--将数据插入t_emp表中之前,先将数据保存到t_emp_copy表中的触发器
create or replace trigger tr1
before
insert on t_emp
for each row
begin
dbms_output.put_line('将要向t_emp表中插入数据...');
insert into t_emp_copy values(:new.id,:new.name,:new.age);
--raise zero_divide;
end;
/
--将数据插入到t_emp_copy表之后,执行的触发器
create or replace trigger tr2
before
insert on t_emp
for each row
begin
dbms_output.put_line('往t_emp_copy表中插入了数据...');
for emp_copy_record in emp_copy_cursor
loop
dbms_output.put_line(emp_copy_record.name);
end loop;
end;
/
例:
create trigger tr1
trigger
数据库对象
命名块,有名字,会被编译并存储在数据库中
当在表、视图、数据库中发生某些事件时,Oracle会自动执行的一段程序
只有在触发器对应的事件发生时,触发器才会执行,触发器是自动执行的一段代码,用户不能调用
触发器的4要素:
1、触发源
用于指定在操作什么时会引发触发器执行
表、视图、数据库
2、触发的事件
用于指定在触发源上执行哪些操作会引发触发器执行
insert 、update 、delete、logon、logonoff
3、触发的时间
用于指定是在操作执行之前、之后,执行触发器
before after
4、触发的频率
用于指定在事件发生时,触发器执行几次
语句级 一条SQL语句,无论操作了几行,触发器只执行一次
行级 一条SQL语句,每操作1行,触发器就执行1次
1、DML触发器
创建语法:
create trigger 触发器名字
{before|after}
{insert|update|delete} on 表名
[for each row]
[when (条件)]
[declare
/*
*定义部分
*/
]
begin
/*
*触发体
*/
[exception
]
end;
for each row
用于指定是行级触发器
when (条件)
触发限制
只有when中指定的条件为true时,才会执行触发器
访问旧行、新行 new old 不需要加冒号
可以为一个触发器指定多个触发事件,多个事件之间通过or分隔
在触发器的底层管理了事务,内部事务?还是不太准确
所以自己写的触发器代码中,不允许写commit、rollback语句
对于DML、instead of触发器
与引发该触发器的DML操作,用的是同一个事务 执行DML操作时,打开的连接关联的事务
在DML触发器的执行过程中
如果发生了错误,会rollback,并会阻止后续操作的执行(before触发器,后面还要执行DML操作)
如果执行成功,不会commit
对于系统触发器
执行时,可能会执行DML操作
发生异常,回滚
成功,提交
例:
单表操作的before、after表级触发器,使用游标取表数据,验证在DML操作执行前后执行触发器
行级触发器的话,表 HWZ.T_EMP 发生了变化, 触发器/函数不能读它
下面例子:验证使用的是同一个事务,出错之后会回滚
create table t_emp_copy as select * from t_emp where 1 = 2;
--将数据插入t_emp表中之前,先将数据保存到t_emp_copy表中的触发器
create or replace trigger tr1
before
insert on t_emp
for each row
begin
dbms_output.put_line('将要向t_emp表中插入数据...');
insert into t_emp_copy values(:new.id,:new.name,:new.age);
--raise zero_divide;
end;
/
--将数据插入到t_emp_copy表之后,执行的触发器
create or replace trigger tr2
before
insert on t_emp
for each row
begin
dbms_output.put_line('往t_emp_copy表中插入了数据...');
for emp_copy_record in emp_copy_cursor
loop
dbms_output.put_line(emp_copy_record.name);
end loop;
end;
/
例:
create trigger tr1