使用ORACLE触发器
来源:互联网 发布:手机数控编程软件 编辑:程序博客网 时间:2024/05/01 22:08
目录
一 使用场景
Oracle触发器,见名知意,就是当条件吻合时,被动触发一系列的DB操作。触发器是由Oracle数据库本身被动触发的动作,与存储过程不同的是,存储过程可以通过外部code或触发器等显示的调用,而触发器是数据库本身的被动行为。例如,当你需要在save A表记录的时候,同时向B表记录save A表的log信息,这样,触发器就很符合您的要求了。
二 环境和备用命令
环境:本篇内容基于CENTOS和oracle 10g调试。
备用命令:
停止oracle服务
启动oracle
其他命令和相关设置:
三 语法介绍
触发器语法
CREATE [OR REPLACE] TRIGGER trigger_name --创建或替换一个触发器,trigger_name指定触发器名称
{BEFORE | AFTER | INSTEAD OF} --指定何时执行触发器
{INSERT | DELETE | UPDATE [OF column [, column …]]} --指定触发变异表的动作
ON {[schema.] table_name | [schema.] view_name} -- 指定被影响的表、schema或视图
[REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
--old修饰访问操作完成前列的值﹐new修饰访问操作完成后列的值
[FOR EACH ROW ] --指定行级触发或表达式触发
[WHEN condition] --指定触发条件
Declare --申明变量
-- 变量;
Begin
--设定触发后执行的代码段
-- trigger_body;
End ;
用途﹕
–1﹐强制执行 business rule.
–2﹐更新其他 table 中的数据.
–3﹐标示数据列以供处理.
–4﹐以信号通知已发生事件
四 注意要点
–1﹐不能使用rollback, commit ,savepoints,transaction交易控制,请具体验证
–2﹐不能使用long , long raw 变量
–3,after 的方式比 before 有效率
–4,行级触发器不可对 trigger 上的本表select,insert,update,delete操作
–5,:new,:old,:parent关键词只可以用在行级触发器中[for each row]
–6,:new,:old,关键词前的冒号只能在触发器体内有效.即在触发器体外不需要冒号,例如在when子句中
–7,:new,:old,伪记录,但是定义的 rowtype 类型的变量不能接受:new,或:old,也不能将:new或:old传递到接受rowtype类型的
–8, 代码大小必须小于32KB
old与new详解:
old修饰访问操作完成前列的值﹐new修饰访问操作完成后列的值
利用 new 与 old 来参考数据域的值
:OLD :NEW
delete 被删除的值 NULL
insert NULL 被建立的值
update 旧值 更改后的新值
在 begin 中使用 , 须加冒号 :
在 when 与 referencing 不须加冒号 :
过程或函数中
–8,触发器数据字典:user_triggers
–9,变异表(mutating table) 和约束表(constrainting table)变异表是当前被DML语句修改的表,对触发器来说变异表就是在其上定义的表.由于执行delete cascade引用完整性约束更新的表也是变异表,约束表是一种需要实施引用完整性约束而读入的表.
–10,触发器中的SQL语句不能进行下列操作:
读或修改触发语句的任何变异表,包括触发表本身
读或修改触发表的约束表中的主键,外键,唯一列
–11,由于在 行级触发器中不能在触发表上使用select,update,delete,update语句,但可以使用语句级触发器,但是如果要使用:new,:old关键词,就必须使用行级触发器,为了既可以使用:new,:old关键词,有可以在触发表上使用select, update, delete, update语句我们可以在一个表上定义两个触发器:一个行级触发器,一个语句级触发器,在行级触发器中,使用:new, :old关键词,在语句级中使用select,update,insert,delete语句,至于如何记录:new的值,我们可以使用package,并在package 中使用table数据类型。
–12,行级触发器和语句级触发器的触发先后顺序:语句级别前,行级级别前,行级级别后,语句级别后。在REFERENCING子句中new前不需要加冒号,该子句需要放在 for each row 之前 。
–13,有 for eache row 关键词的为 行级触发器,否则是语句级触发器
–选择性启动 TRIGGER﹐使用关键词deleting,updating,inserting
–如果是因为delete而执行trigger﹐则返回true
–如果是因为update而执行trigger﹐则返回true
–如果是因为insert而执行trigger﹐则返回true
五 实战实例
☆创建一个触发器:
上面的名为demo_trigger的触发器定义了当更新USER表记录完成的时候向user_info表插入一条记录。
☆指定触发前执行:
将前例中的AFTER关键字换成BEFORE即可。如果设定为AFTER则是在完成后,见上一个例子。
☆指定触发动作:
这里指定了触发的动作为更新user表成功后,你也可以指定为插入或更新或删除时执行触发器
☆使用:new和:old来引用变异表的记录
CREATE OR REPLACE TRIGGER demo_trigger
AFTER UPDATE ON "user"
REFERENCING OLD AS "USER_BEFORE_UPDATED" NEW AS "USER_AFTER_UPDATED"
FOR EACH ROW
DECLARE
BEGIN
INSERT INTO user_info
VALUES
(sysdate,"update a record into user table.",
:USER_BEFORE_UPDATED.userstatus,
:USER_AFTER_UPDATED.userstatus );
END;
这里使用REFERENCING OLD AS “USER_BEFORE_UPDATED” NEW AS “USER_AFTER_UPDATED” 来记录更新前和更新后USER表的记录,并指定别名,在代码块中可以使用这些别名来引用记录值,如 :USER_BEFORE_UPDATED.userstatus 。
REFERENCING 子句必须放在 FOR EACH ROW子句之前。
☆指定触发条件
CREATE OR REPLACE TRIGGER demo_trigger
AFTER UPDATE ON "user"
REFERENCING OLD AS "USER_BEFORE_UPDATED" NEW AS "USER_AFTER_UPDATED"
FOR EACH ROW
WHEN(NEW.age >= 60 OR old.age >= 60)
DECLARE
BEGIN
INSERT INTO user_info
VALUES
(sysdate,"update a record into user table.",
:USER_BEFORE_UPDATED.userstatus,
:USER_AFTER_UPDATED.userstatus );
END;
上例使用WHEN(NEW.age >= 60 OR old.age >= 60) 限定只有当新记录或老记录的age>=60时,才执行触发器指定的代码段。
☆声明变量
CREATE OR REPLACE TRIGGER demo_trigger
AFTER UPDATE ON "user"
REFERENCING OLD AS "USER_BEFORE_UPDATED" NEW AS "USER_AFTER_UPDATED"
FOR EACH ROW
WHEN(NEW.age >= 60 OR old.age >= 60)
DECLARE
olduserstatus varchar2(20);
newuserstatus varchar2(20);
dtime number;
BEGIN
INSERT INTO user_info
VALUES
(sysdate,"update a record into user table.",
:USER_BEFORE_UPDATED.userstatus,
:USER_AFTER_UPDATED.userstatus );
END;
上例通过DECLARE 声明了olduserstatus, newuserstatus, dtime 三个变量,您还可以在代码段中使用他们,如下:
CREATE OR REPLACE TRIGGER demo_trigger
AFTER UPDATE ON "user"
REFERENCING OLD AS "USER_BEFORE_UPDATED" NEW AS "USER_AFTER_UPDATED"
FOR EACH ROW
WHEN(NEW.age >= 60 OR old.age >= 60)
DECLARE
olduserstatus varchar2(20);
newuserstatus varchar2(20);
dtime number;
BEGIN
olduserstatus := 'olduserstatus ';
--将当前系统时间计算成数值型并赋值给dtime
SELECT (sysdate - 8 / 24 - to_date('1970-01-01', 'yyyy-mm-dd')) * 86400000
INTO dtime from dual;
INSERT INTO user_info
VALUES
(dtime ,"update a record into user table.",
olduserstatus ,
:USER_AFTER_UPDATED.userstatus );
END;
☆编写触发后执行的代码段
CREATE OR REPLACE TRIGGER demo_trigger
AFTER INSERT OR UPDATE ON "user"
REFERENCING OLD AS "USER_BEFORE_UPDATED" NEW AS "USER_AFTER_UPDATED"
FOR EACH ROW
WHEN(NEW.age >= 60 OR old.age >= 60)
DECLARE
olduserstatus varchar2(20);
newuserstatus varchar2(20);
dtime number;
BEGIN
olduserstatus := 'olduserstatus ';
--将当前系统时间计算成数值型并赋值给dtime
SELECT (sysdate - 8 / 24 - to_date('1970-01-01', 'yyyy-mm-dd')) * 86400000
INTO dtime from dual;
IF updating THEN
INSERT INTO user_info
VALUES
(dtime ,"update a record into user table.",
olduserstatus ,
:USER_AFTER_UPDATED.userstatus );
ELSIF inserting THEN
INSERT INTO user_info
VALUES
(dtime ,"INSERT a record into user table.",
olduserstatus ,
:USER_AFTER_UPDATED.userstatus );
END IF;
END;
上面通过在”BEGIN END”代码段中使用IF判断当前动作是update 或 insert 而执行不同的代码段。关于触发动作返回值具体可参考注意要点第13条。
六 特别提醒
计算时间
--将当前系统时间计算成数值型并赋值给dtime
--current_timestamp(3) 表示截取3位有效位
select ((SYSTIMESTAMP - 8 / 24 - to_date('1970-01-01', 'yyyy-mm-dd')) * 86400000 )
+ (to_char(current_timestamp(3),'FF') ) from dual;
通过sql为变量赋值:使用SELECT INTO 变量名来进行赋值。
何时使用冒号来使用变量:
对于在REFERENCING 后为old 和 new定义的别名,在代码块中需要使用冒号:来引用;对于DECLARE 中定义的变量在代码块中则不需要使用冒号;
在WHEN子句中使用NEW 和 OLD不需要使用冒号。
为变量赋值须使用 冒号等于号 := 来赋值。
- oracle使用八(触发器)
- Oracle触发器的使用
- oracle触发器使用笔记
- oracle触发器使用
- Oracle触发器的使用
- oracle触发器使用
- Oracle中使用触发器
- oracle触发器使用笔记
- Oracle触发器使用介绍
- Oracle触发器使用介绍
- oracle 触发器使用
- 使用ORACLE触发器
- oracle禁止使用触发器
- oracle触发器的使用
- Oracle触发器使用介绍
- Oracle触发器使用实例
- Oracle使用触发器实例
- Oracle触发器使用
- Linux下时间机制
- system()和execve()区别
- 论坛群发,论坛顶贴验证码识别解决方案
- 穆利堂推荐-新公司应该怎么雇佣人才?
- Oracle PL/SQL语法
- 使用ORACLE触发器
- booting ext3
- oracle触发器中定义变量
- 黑马程序员-java专题系列之2-字符编码
- Flash Builder 4.7 正式版下载地址
- jboss7.1.1配置mysql数据源
- oracle连接“监听程序当前无法识别连接描述符中请求的服务”,你是怎么解决的。
- Windows下安装MariaDB
- 黑马程序员-java专题系列之3-日期