Oracle  行级触发器
在创建触发器时,如果使用了FOR EACH ROW选项,则创建的该触发器为行级触发器。对于行级触发器而言,当一个DML语句操作影响到数据库中的多行数据时,行级触发器会针对于每一行执行一次。
在行级触发器中有一个很重要的特点,当创建BEFORE行级触发器时,可以在触发器中引用受到影响的行值,甚至可以在触发器中设置它们。
下面将在表上创建一个行级触发器,并使用一种数据库对对象(序列)生主键值。这是非常常见的FOR EACH ROW触发器的用途。
(1)创建一个测试表FOO,以及随同使用的序列,序列的作用是自动生成一组排序数。
SQL> --创建一个表
SQL> create table foo(sid number,sname varchar2(20));
表已创建。
SQL> --创建序列
SQL> create sequence seq_foo;
序列已创建。
(2)创建生成主键的行级触发器。
SQL> create or replace trigger foo_trigger
  2    before insert or update of sid
  3    on foo
  4    for each row--行级触发器
  5  begin
  6    if inserting then
  7      select val
  8      into :new.sid
  9      from dual;
10    else
11      raise_application_error(-20020,'不允许更新ID值!');
12    end if;
13  end;
14  /
触发器已创建
(3)现在可以尝试向表FOO添加两行数据,以测试触发器是否能够成功运行。
SQL> insert into foo(sid,sname)
  2  values(1,'董鹏');
已创建 1 行。
sql触发器的使用SQL>
SQL> insert into foo(sname)
  2  values('刘丽');
已创建 1 行。
SQL> select * from foo;
      SID  SNAME
  ----------  --------------------
        1    董鹏
        2    刘丽
从查询结果中可以看出,无论是否为SID列的提供值,SID列的值都会使用seq_foo.NEXTVAL的值值,这是因为在表中引用了:NEW.SID值。
在行级触发器中,可以访问受到影响的行值,这主要是通过引用列名称的相关性标识符来实现。通过引用具有相关性标识符的列,就可以获取语句执行前和语句执行后的值。前映像的默认相关性标识符为:OLD,后映像的相关性标识符为:NEW。在引用受影响的列值时,需要注意以下几点:
在INSERT触发器中,由于不存先前的数据,所以不能使用前映像:OLD,只能使用后映像:NEW。
与此相反,在DELETE触发器中则没有后映像:NEW的值。
对于UPDATE触发器而言,才同时具有各个列的前映像值:NEW和后映像值:OLD。
在定义触发器时,可以使用REFERENCING子句改变列的相关名称。例如,在下面的示例中将使用REFERENCING子句指定相关性标识符的名称,重新定义了触发器foo_trigger
SQL> create or replace trigger foo_trigger
  2    before insert or update of sid
  3    on foo
  4    referencing new as new_value
  5                old as old_value
  6    for each row--行级触发器
  7  begin
  8    if inserting then
  9      select val
10      into :new_value.sid
11      from dual;
12    else
13      raise_application_error(-20020,'不允许更新ID值!');
14    end if;
15  end;
16  /
触发器已创建
通常没有必须重命名:NEW和:OLD,Oracle提供这个能力是为了避免混淆相似的命名对象。因此,如果没有必要,应该尽量避免改变相关名称。