日志文章

2008年03月07日 20:11:38

oracle触发器求助!!!

oracle触发器求助!!!!

提交时间: Nov 8, 2005 4:18:40 PM


首先创建表A和表B
create table A(
  col1 varchar2(10),
  col2 varchar2(50),
  col3 varchar2(10));

create table B(    
tablename varchar2(10),  
primarykey varchar2(255),  
rowkey varchar2(255),  
operation varchar2(10));

之后创建oracle update触发器
create or replace trigger cdcTriUpdate
after update on a
for each row
declare
-- local variables here
begin
IF updating('col1')
THEN    
INSERT INTO b    
(tablename,primarykey,rowkey,operation)  
VALUES    
('A','A.col1='||:new.col1 ,'1','update');
END IF;
IF updating('col2')
THEN    
INSERT INTO b    
(tablename,primarykey,rowkey,operation)  
VALUES    
('A','A.col2='||:new.col2 ,'2','update');
END IF;
IF updating('col3')
THEN    
INSERT INTO b    
(tablename,primarykey,rowkey,operation)  
VALUES    
('A','A.col3='||:new.col3 ,'3','update');
END IF;
end cdcTriUpdate;

功能是当对表A进行update,立刻触发写入表B中,

得到(表名,update的值,列,操作类型)

但是当以col1为主键,同时更新两列或更多列的时候,更新的列不会写在一起,

而是分两条记录来写的,问,如何才能写在一条记录里面?
功能:
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, [url=mailto:%20donny@hotmail.com%20,60,10000,.25]‘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


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1711633

Tags: oracle   触发器   求助  

类别: SQL |  评论(1) |  浏览(1725) |  收藏
1楼 [匿名]ymwa9noe 2008年08月15日 12:58:56 Says:
%5Burl=http://www.lxwltg.com/%5D%E5%88%9B%E9%B8%BF%E8%BD%AF%E4%BB%B6%EF%BC%8C%E7%8E%B0%E5%9C%A8%E5%8F%AF%E4%BB%A5%E5%90%914200%E5%AE%B6%E5%9B%BD%E5%86%85%E5%88%86%E7%B1%BB%E4%BF%A1%E6%81%AF%E6%B8%AF%E5%8F%91%E5%B8%83%E4%BE%9B%E6%B1%82%E4%BF%A1%E6%81%AF%EF%BC%8C600%E5%AE%B6%E7%9A%84%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E%E7%99%BB%E9%99%86%EF%BC%8C800%E5%AE%B6%E7%9A%84%E9%BB%84%E9%A1%B5%E7%99%BB%E9%99%86%EF%BC%8C%E5%B9%B6%E4%B8%94%E5%8C%85%E6%8B%AC36000%E4%B8%AA%E5%90%84%E4%B8%AA%E7%B1%BB%E5%88%AB%E7%9A%84%E5%8F%AF%E5%8F%91%E5%B8%83%E5%95%86%E5%8A%A1%E4%BF%A1%E6%81%AF%E7%9A%84%E7%BB%BC%E5%90%88%E7%BD%91%E7%AB%99%E4%BF%A1%E6%81%AF%E5%B9%BF%E6%92%AD%E5%8A%9F%E8%83%BD%EF%BC%8C%E6%88%90%E5%8A%9F%E7%8E%87%E6%97%A0%E5%8F%AF%E6%AF%94%E6%8B%9F%EF%BC%8C%E9%AA%8C%E8%AF%81%E7%A0%81%E5%87%A0%E4%B9%8E%E5%81%9A%E5%88%B0%E4%BA%86%E5%85%A8%E8%87%AA%E5%8A%A8%E8%AF%86%E5%88%AB%EF%BC%8C%E8%87%AA%E5%8A%A8%E5%A1%AB%E5%86%99%EF%BC%81%E5%B9%B6%E4%B8%94%E5%A2%9E%E5%8A%A0%E4%BA%86%E6%AF%8F%E5%A4%A9%E6%88%96%E6%AF%8F%E5%91%A8%E6%88%96%E6%AF%8F%E6%9C%88%E5%85%A8%E8%87%AA%E5%8A%A8%E6%89%A7%E8%A1%8C%E8%AE%A1%E5%88%92%E4%BB%BB%E5%8A%A1%E7%9A%84%E5%BC%BA%E5%A4%A7%E5%8A%9F%E8%83%BD%EF%BC%81%E6%97%A0%E9%9C
发表评论