oracle触发器update本表数据
功能: 
1、 允许/限制对表的修改 
2、 自动生成派生列,比如自增字段 
3、 强制数据一致性 
4、 提供审计和日志记录
5、 防止无效的事务处理 
6、 启用复杂的业务逻辑 
开始 
create trigger 
biufer_employees_department_id 
before insert or update 
of department_id
on employees 
referencing old as old_value 
new as new_value 
for 
each row 
when (new_value.department_id<>80 ) 
begin
:new_value.commission_pct :=0; 
end; 
/ 
触发器的组成部分: 
1、 触发器名称
2、 触发语句 
3、 触发器限制 
4、 触发操作 
1、 触发器名称 
create trigger 
biufer_employees_department_id 
命名习惯: 
biufer(before insert update for 
each row) 
employees 表名 
department_id 列名 
2、 触发语句 
比如:
表或视图上的DML语句 
DDL语句 
数据库关闭或启动,startup shutdown 等等 
before insert or 
update 
of department_id 
on employees 
referencing old as old_value
new as new_value 
for each row 
说明: 
1、 无论是否规定了department_id 
,对employees表进行insert的时候 
2、 对employees表的department_id列进行update的时候 
3、 
触发器限制 
when (new_value.department_id<>80 )
限制不是必须的。此例表示如果列department_id不等于80的时候,触发器就会执行。 
其中的new_value是代表跟新之后的值。
4、 触发操作 
是触发器的主体 
begin 
:new_value.commission_pct :=0; 
end;
主体很简单,就是将更新后的commission_pct列置为0 
触发: 
insert into 
employees(employee_id,
last_name,first_name,hire_date,job_id,email,department_id,salary,commission_pct 
) 
values( 12345,'Chen','Donny', sysdate, 12, 
‘donny@hotmail.com',60,10000,.25); 
select commission_pct from employees 
where employee_id=12345; 
触发器不会通知用户,便改变了用户的输入值。 
触发器类型: 
1、 语句触发器
2、 行触发器 
3、 INSTEAD OF 触发器 
4、 系统条件触发器 
5、 用户事件触发器 
1、 语句触发器
是在表上或者某些情况下的视图上执行的特定语句或者语句组上的触发器。能够与INSERT、UPDATE、
DELETE或者组合上进行关联。但是无论使用什么样的组合,各个语句触发器都只会针对指定语句激活一次
。比如,无论update多少行,也只会调用一次update语句触发器。 
例子:
需要对在表上进行DML操作的用户进行安全检查,看是否具有合适的特权。 
Create table foo(a number);
Create trigger biud_foo 
Before insert or update or delete 
On foo
Begin 
If user not in (‘DONNY') then 
Raise_application_error(-20001, 
‘You don't have access to modify this table.'); 
End if; 
End; 
/
即使SYS,SYSTEM用户也不能修改foo表 
[试验] 
对修改表的时间、人物进行日志记录。 
1、 建立试验表
create table employees_copy as select *from hr.employees 
2、 建立日志表
create table employees_log( 
who varchar2(30), 
when date); 
3、 
在employees_copy表上建立语句触发器,在触发器中填充employees_log 表。 
Create or replace trigger 
biud_employee_copy 
Before insert or update or delete 
On employees_copy
Begin 
Insert into employees_log( 
Who,when) 
Values( user, 
sysdate); 
End; 
/ 
4、 测试 
update employees_copy set salary= 
salary*1.1; 
select *from employess_log; 
5、 确定是哪个语句起作用?
即是INSERT/UPDATE/DELETE中的哪一个触发了触发器? 
可以在触发器中使用INSERTING / UPDATING / 
DELETING 条件谓词,作判断: 
begin 
if inserting then 
----- 
elsif updating 
then 
----- 
elsif deleting then 
------ 
end if; 
end; 
if 
updating(‘COL1') or updating(‘COL2') then 
------ 
end if; 
[试验] 
1、 
修改日志表 
alter table employees_log 
add (action varchar2(20)); 
2、 
修改触发器,以便记录语句类型。 
Create or replace trigger biud_employee_copy 
Before 
insert or update or delete 
On employees_copy 
Declare 
L_action 
employees_log.action%type; 
Begin 
if inserting then
l_action:='Insert'; 
elsif updating then 
l_action:='Update';
elsif deleting then 
l_action:='Delete'; 
else
raise_application_error(-20001,'You should never ever get this error.');
Insert into employees_log( 
Who,action,when) 
Values( user, 
l_action,sysdate); 
End; 
/ 
3、 测试 
insert into employees_copy( 
employee_id, last_name, email, hire_date, job_id)
values(12345,'Chen','Donny@hotmail',sysdate,12); 
select *from 
employees_log 
update employees_copy set salary=50000 where employee_id = 
12345; 
2、 行触发器 
是指为受到影响的各个行激活的触发器,定义与语句触发器类似,有以下两个例外:
1、 定义语句中包含FOR EACH ROW子句 
2、 在BEFORE……FOR EACH ROW触发器中,用户可以引用受到影响的行值。
比如: 
定义: 
create trigger biufer_employees_department_id 
before 
insert or update 
of department_id 
on employees_copy 
referencing old 
as old_value 
new as new_value 
for each row 
when 
(new_value.department_id<>80 ) 
begin 
:new_value.commission_pct 
:=0; 
end; 
/ 
Referencing 子句: 
执行DML语句之前的值的默认名称是 :old ,之后的值是 :new
insert 操作只有:new 
delete 操作只有 :old 
update 操作两者都有
referencing子句只是将new 和old重命名为new_value和old_value,目的是避免混淆。比如操作一个名为 
new的表时。
作用不很大。 
[试验]:为主健生成自增序列号 
drop table foo; 
create table foo(id 
number, data varchar2(20)); 
create sequence foo_seq; 
create or replace 
trigger bifer_foo_id_pk 
before insert on foo 
for each row 
begin
select foo_seq.nextval into :new.id from dual; 
end; 
/ 
insert 
into foo(data) values(‘donny'); 
insert into foo values(5,'Chen'); 
select 
* from foo; 
3、 INSTEAD OF 触发器更新视图 
Create or replace 
view company_phone_book as 
Select first_name||', '||last_name name, email, 
phone_number, 
employee_id emp_id 
From hr.employees; 
尝试更新email和name
update hr.company_phone_book 
set name='Chen1, Donny1' 
where 
emp_id=100 
create or replace trigger update_name_company_phone_book
INSTEAD OF 
Update on hr.company_phone_book 
Begin 
Update 
hr.employees 
Set employee_id=:new.emp_id, 
First_name=substr(:new.name, 
instr(:new.name,',')+2), 
last_name= 
substr(:new.name,1,instr(:new.name,',')-1), 
phone_number=:new.phone_number,
email=:new.email 
where employee_id=:old.emp_id; 
end; 
4、 
系统事件触发器 
系统事件:数据库启动、关闭,服务器错误 
create trigger ad_startup 
after 
startup 
on database 
begin 
-- do some stuff 
end; 
/
5、 用户事件触发器 
用户事件:用户登陆、注销,CREATE / ALTER / DROP / ANALYZE 
/ AUDIT / GRANT / REVOKE / 
RENAME / TRUNCATE / LOGOFF 
例子:记录删除对象 
1. 
日志表 
create table droped_objects( 
object_name varchar2(30),
object_type varchar2(30), 
dropped_on date); 
2.触发器 
create or 
replace trigger log_drop_trigger 
before drop on donny.schema 
begin
insert into droped_objects values( 
ora_dict_obj_name, -- 与触发器相关的函数
ora_dict_obj_type, 
sysdate); 
end; 
/ 
3. 测试
create table drop_me(a number); 
create view drop_me_view as select *from 
drop_me; 
drop view drop_me_view; 
drop table drop_me; 
select *from 
droped_objects 
禁用和启用触发器 
alter trigger <trigger_name> disable;
alter trigger <trigger_name> enable; 
事务处理: 
在触发器中,不能使用commit / 
rollback 
因为ddl语句具有隐式的commit,所以也不允许使用 
视图: 
dba_triggers
本文转自http://www.jb51.net/article/18252.htm
oracle触发器update本表数据的更多相关文章
- MySQL触发器更新本表数据异常:Can't update table 'tbl' in stored function/trigger because it
		MySQL触发器更新本表数据异常:Can't update table 'tbl' in stored function/trigger because it 博客分类: 数据库 MySQLJava ... 
- Oracle通过Navicat导入表数据与机构,数据无法直接查询,需要加双引号的问题
		使用navicat 导入表到ORACLE时,总是会遇到虽然表格完整导入到数据库,但是往往查不出来数据,网上提供的解决办法是把查询的列 加上 双引号,或者表名加上双引号,但这解决办法却减慢了编写sql ... 
- oracle中字符串与表数据拼接的用法--“||”
		测试过程中,经常需要批量删除或者插入.修改一些表数据或结构,使用手工复制.粘贴其实很麻烦,所以这是我们就可以使用拼接成sql语句的方法来实现操作数据.下面先讲讲oracle中拼接符 || 的用法,如下 ... 
- MySQL - 问题集 - 触发器更新本表数据异常"Can’t update table ‘tbl’ in stored function/trigger because it is already used by statement which invoked this"
		如果你在触发器里面对刚刚插入的数据进行了 insert/update, 则出现这个问题.因为会造成循环的调用. create trigger test before update on test fo ... 
- oracle触发器,一个表新增、修改的同时同步另一张表
		oracle创建触发器,把本地新增.修改数据过程同步到另一个服务器上去. 如果是本地,加数据库名即可.如果是远程服务器,不是一台机器,做一个db_link操作即可. ----------------- ... 
- 关于从Oracle数据库中删除表数据
		1,删除表 drop 1.1 执行drop table table_name 语句 被 drop后的表被放在用户回收站(user_recyclebin)里,而没有被直接删除掉,回收站里的表可以被恢复 ... 
- C# Oracle.ManagedDataAccess 批量更新表数据
		这是我第一次发表博客.以前经常到博客园查找相关技术和代码,今天在写一段小程序时出现了问题, 但在网上没能找到理想的解决方法.故注册了博客园,想与新手分享(因为本人也不是什么高手). vb.net和C# ... 
- oracle如何查询哪个表数据量大
- oracle 查询之前的表数据
		SELECT * FROM Student AS OF TIMESTAMP SYSDATE - 3/1440 对SQL的解释说明: SYSDATE :当前时间 1440 :24h*60m=1440m ... 
随机推荐
- Redis在Windows环境配置多实例多端口运行
			Redis是一种跨平台NoSql内存数据库,这几年各大公司系统应用中非常多见,支持多种数据类型,可以持久化保存数据,很多公司直接拿来作为数据库使用. 相比于Memcached,Redis支持持久化保存 ... 
- uboot初识
			一. 什么是uboot 1.1. uboot的由来 1.1.1. uboot是SourceForge上的开源项目 1.1.2. uboot就是由一个人发起,然后由整个网络上所有感兴趣的人共同维护发展而 ... 
- c++ 多线程(2000个)端口扫描(附源码)
			目录 程序适应环境与基本介绍 程序适应环境与基本介绍 情况:开2000个线程,扫描主机上开启的端口,扫描时间40秒左右. 瓶颈:不管开5000还是更多,都不能大幅加快扫描时间. 瓶颈解决方法:可以使用 ... 
- hive中的索引创建
			1.在hive中创建索引所在表 create table if not exists h_odse.hxy(id int,name string,hobby array<string>,a ... 
- Cleaning Robot (bfs+dfs)
			Cleaning Robot (bfs+dfs) Here, we want to solve path planning for a mobile robot cleaning a rectangu ... 
- 说说无线路由器后门的那些事儿(1)-D-Link篇
			[原创]说说无线路由器后门的那些事儿(1)-D-Link篇 作 者: gamehacker 时 间: 2013-11-29,11:29:19 链 接: http://bbs.pediy.com/sho ... 
- MATLAB图像的代数运算
			1.图像旋转与缩放 bm=imread("3.png"); %subplot(1,3,1); imshow(bm); %缩放图片 %bt=imresize(bm,0.5,'near ... 
- 关于代码手写UI,xib和StoryBoard
			代码手写UI 这种方法经常被学院派的极客或者依赖多人合作的大型项目大规模使用.Geek们喜欢用代码构建UI,是因为代码是键盘敲出来的,这样可以做到不开IB,手不离开键盘就完成工作,可以专注于编码环境, ... 
- .net 正则表达式
			string RegStr = @"^[0-9]*[1-9][0-9]*$"; if (Regex.IsMatch("待验证的字符串", RegStr)) { ... 
- SolrCloud集群
			1 SolrCloud简介 1.1什么是SolrCloud SolrCloud(solr 云)是 Solr 提供的分布式搜索方案,当你需要大规模,容错,分布式索引和检索能力时使用 SolrCloud. ... 
