精华内容
下载资源
问答
  • ORACLE系统里,触发器类似过程和函数,都有声明,执行和异常处理过程的PL/SQL块。1.说明1)触发器是一种特殊的存储过程,触发器一般由事件触发并且不能接受参数,存储器由语句块去调用2)触发器分类:1.DML触发器: ...

    触发器 是特定事件出现的时候,自动执行的代码块。类似于存储过程,但是用户不能直接调用他们。触发器是许多关系数据库系统都提供的一项技术。在ORACLE系统里,触发器类似过程和函数,都有声明,执行和异常处理过程的PL/SQL块。

    1.说明

    1)触发器是一种特殊的存储过程,触发器一般由事件触发并且不能接受参数,存储器由语句块去调用

    2)触发器分类:

    1.DML触发器: 创建在表上,由DML事件引发

    2.instead of触发器: 创建在视图上并且只能在行级上触发,用于替代insert,delete等操作(由于oracle中不能直接对有两个以上的表建立的视图进行DML操作,所以给出替代触发器,它是专门为进行视图操作的一种处理方法)

    3.DDL触发器: 触发事件时数据库对象的创建和修改

    4.数据库事件触发器:定义在数据库或者模式上,由数据库事件触发

    3)组成:

    1.触发事件:引发触发器被触发的事件 DML语句(INSERT, UPDATE, DELETE语句对表或视图执行数据处理操作)、DDL语句(如CREATE、ALTER、DROP语句在数据库中创建、修改、删除模式对象)、数据库系统事件

    (如系统启动或退出、异常错误)、用户事件(如登录或退出数据库)。

    2.触发时间:即该触发器是在触发事件发生之前(BEFORE)还是之后(AFTER)触发

    3.触发操作:触发器触发后要完成的事情

    4.触发对象:包括表、视图、模式、数据库。只有在这些对象上发生了符合触发条件的触发事件,触发器才会执行触发操作。

    5.触发条件:由WHEN子句指定一个逻辑表达式。只有当该表达式的值为TRUE时,遇到触发事件才会自动执行触发操作。

    6.触发频率:说明触发器内定义的动作被执行的次数。即语句级(STATEMENT)触发器和行级(ROW)触发器。(比如delete多条数据时,行级触发器可能会执行多次,语句级触发器只会触发一次)

    2.语法

    1)说明

    不同类型的触发器例如DML触发器,Instead of触发器,系统触发器语法格式区别较大

    2)一般语法

    CREATE [OR REPLACE] TIGGER触发器名 触发时间 触发事件  ON表名/视图名  [FOR EACH ROW]  //加上FOR EACH ROW 即为行级触发器,不加时为语句级触发器  BEGIN  pl/sql语句  END

    create [or replace] trigger [schema.]trigger_name      {before | after | instead of}      {delete [or insert][or update [of column,...n]]}      on [schema.]table_name | view_name      [for each row [when(condition)]]      sql_statement[,...n]

    例如:

    CREATE OR REPLACE TRIGGER   trigger_name       ON table_name  [FOR EACH ROW]  WHEN (condition)  DECLARE  BEGIN  END;

    3)instead of 触发器语法

    语法:

    CREATE [OR REPLACE] TRIGGER trigger_name INSTEAD OF{INSERT|DELETE|UPDATE [OF COLUMN...]}[OR {INSERT| DELETE| UPDATE [OF COLUMN...]}]ON VIEW_NAME[REFFERENCING{OLD [AS] OLD | NEW [AS] NEW| PARENT AS PARENT}]   // 可以指定相关名称,当前的默认相关名称为OLD和NEW,应用相关名称时需要加:[FOR EACH ROW]  //instead of 触发器只能在行级上触发,因为没有必要指定[WHEN CONDITION]DECLAREBEGINEND;

    说明:INSTEAD OF 用于对视图的DML触发,由于视图可能有多个表进行联结而成,因而并非所有的联结均可更新,运用 INSTEAD OF 触发器可完成相应的操作。

    3.实例

    创建测试表格:

    CREATE TABLE "HNZC"."TRIGGERTEST"  (    "ID"    VARCHAR2(20 BYTE),    "NAME"  VARCHAR2(20 BYTE),    "SCORE" NUMBER  );create table tab1 select * from triggertest;

    1)DML触发器/行级触发器

    触发器如下:

    CREATE OR REPLACE TRIGGER TRIGGER1 AFTER INSERT ON TRIGGERTEST    //插入后触发FOR EACH ROW                   //行级触发器BEGIN   INSERT INTO tab1(ID,NAME) VALUES('22','33');END;

    执行语句:

    insert into triggertest (id) values ('aabbcc');

    语句执行结束,表tab1中新增加一条数据

    2)限制对表的修改(例如非工作时间不能修改某些表)

    触发器如下:

    CREATE OR REPLACE TRIGGER TRIGGER1 AFTER INSERT ON TRIGGERTEST FOR EACH ROW BEGIN   IF(TO_CHAR(SYSDATE,'DAY') IN ('星期三','星期天'))   THEN RAISE_APPLICATION_ERROR(-20001,'不是上班时间,不能修改表格triggertest');   END IF;END;

    执行语句:

    insert into triggertest (id) values ('aabbcc');

    今天周三因而输出结果为:

    在行 1 上开始执行命令时出错:insert into triggertest (id) values ('aabbcc')错误报告:SQL 错误: ORA-20001: 不是上班时间,不能修改表格triggertestORA-06512: 在 "HNZC.TRIGGER1", line 3ORA-04088: 触发器 'HNZC.TRIGGER1' 执行过程中出错

    通常对表的修改限制如下(即周一至周五9——18点能修改表格)

    CREATE OR REPLACE TRIGGER TRIGGER1 BEFORE INSERT OR DELETE OR UPDATE ON TRIGGERTEST FOR EACH ROW BEGIN   IF(TO_CHAR(SYSDATE,'DAY') IN ('星期六','星期天'))   OR(TO_CHAR(SYSDATE,'HH24:MI') NOT BETWEEN '9:00' AND '18:00')   THEN RAISE_APPLICATION_ERROR(-20001,'不是上班时间,不能修改表格triggertest');   END IF;END;

    3)增加限制条件(如不能更改某个员工的记录)

    触发器如下:(如下实现月儿的分数只能增加)

    CREATE OR REPLACE TRIGGER TRIGGER1 BEFORE INSERT OR DELETE OR UPDATE ON TRIGGERTEST FOR EACH ROW WHEN(OLD.NAME='月儿')BEGIN   CASE WHEN UPDATING('SCORE') THEN        IF:NEW.SCORE<:old.score>

    当前月儿的分数为20

    当修改为10时出错

    UPDATE "HNZC"."TRIGGERTEST" SET SCORE = '10' WHERE ROWID = 'AAAdEzAAPAAAAH+AAB' AND ORA_ROWSCN = '47685303'ORA-20001: 月儿的分数只能提升不能下降ORA-06512: 在 "HNZC.TRIGGER1", line 4ORA-04088: 触发器 'HNZC.TRIGGER1' 执行过程中出错

    当修改为30时成功

    UPDATE "HNZC"."TRIGGERTEST" SET SCORE = '30' WHERE ROWID = 'AAAdEzAAPAAAAH+AAB' AND ORA_ROWSCN = '47685303'提交成功

    4)在触发器中调用存储过程

    触发器为:

    CREATE OR REPLACE TRIGGER TRIGGER1 BEFORE INSERT OR DELETE OR UPDATE ON TRIGGERTEST FOR EACH ROW BEGIN  TESTPRO1();END;

    存储过程为:

    create or replacePROCEDURE TESTPRO1 AS BEGIN insert into tab1(id,name,score) VALUES('AAA','BBB',200);END TESTPRO1;

    执行完毕后tab1中增加一条数据

    5)级联更新

    触发器如下(triggertest表中name修改时同时修改tab1中的name)

    create or replacePROCEDURE TESTPRO1 AS BEGIN insert into tab1(id,name,score) VALUES('AAA','BBB',200);END TESTPRO1;

    执行语句:

    update  triggertest set name= '水儿' where name='月儿';

    结果:tab1中name为月儿的也更改为水儿

    6)instead of触发器

    TABLE STUDENT表格数据如下

    cfaea9e8edc5e9080079b1eca4713ae1.png

    创建视图student_view

    CREATE OR REPLACE VIEW STUDNET_VIEW AS SELECT CLASSID,AVG(SCORE) AVERAGE_SCORE FROM STUDENTGROUP BY CLASSID;

    视图数据如下:

    52d55e8a84c5b97775b047623d7afafa.png

    对视图student_view 执行如下操作:

    DELETE FROM STUDNET_VIEW WHERE CLASSID='111';

    执行结果:

    错误报告:SQL 错误: ORA-01732: 此视图的数据操纵操作非法01732. 00000 -  "data manipulation operation not legal on this view"

    解决方法:创建INSTEAD OF 视图

    CREATE OR REPLACE TRIGGER STUDENT_VIEW_DELETE INSTEAD OF DELETE ON STUDNET_VIEW FOR EACH ROWBEGIN  DELETE FROM STUDENT WHERE CLASSID=:OLD.CLASSID;END STUDENT_VIEW_DELETE;

    执行删除语句

    DELETE FROM STUDNET_VIEW WHERE CLASSID='111';

    执行结果:删除成功

    1 行已删除。

    4.注意事项

    1) 在触发器的执行部分只能用DML语句(SELECT、INSERT、UPDATE、DELETE),不能使用DDL语句(CREATE、ALTER、DROP)

    2) 触发器中不能使用commit语句,触发器的操作与触发事件(INSERT,UPDATE,DELETE)一起进行COMMIT和ROLLBACK;

    3)  一个表上的触发器越多,对于表的DML操作性能影响越大

    4) 触发器最大为32K

    展开全文
  • Oracle触发器

    千次阅读 2018-08-18 13:52:35
    Oracle触发器 触发器是一个能够自动执行的PLSQL块。 当表的状态发生改变的时候,那么该表中对应的触发器就会自动触发,然后执行触发器中PLSQL块。 触发器监控表的记录是否 修改【insert、update、delete】 ...

    Oracle触发器

    触发器是一个能够自动执行的PLSQL块。
    当表的状态发生改变的时候,那么该表中对应的触发器就会自动触发,然后执行触发器中PLSQL块。
    
    触发器监控表的记录是否 修改【insertupdatedelete

    创建触发器

    create or replace trigger 触发器的名称
    after|before --触发时间:在执行DML操作之前before或之后after触发;
    insert|update|delete --触发事件:常用的触发事件有添加insert、修改update、删除deleteon 表名 --on 指定表名 ,用of指定列名
    
    [for each row]  --如果指定该参数,那么每影响一条记录就会触发一次
    
    declare
    
    begin 
      --触发动作:就是一个PLSQL块;
    end;
    --创建一个触发器
    create or replace trigger tri_add_emp
    before  --触发事时间
    insert on emp  --触发事件
    for each row
    begin
      dbms_output.put_line('触发动作...'); --触发动作
    end;
    --创建一个触发器:当前emp表有数据插入的时候,我们在控制台输出:你插入成功啦!
    create or replace trigger tri_emp_insert_data_success
    after
    insert
    on emp
    declare
    
    begin 
       dbms_output.put_line('你插入成功啦!');
    end;
    
    
    --测试:
    insert into emp (empno,ename) values (8888,'aaaa');
    commit;
    
    
    select * from emp;
    
    
    --监控员工表,监控update动作,不能给员工降薪
    /*
    我们想获取更新之后与更新之前的值:
           必须使用行级触发器
           for each row    
             使用::old   旧的值  , :new  新的值
    
    
    弹窗函数; raise_application_error(v1,p1) 
             v1: 取值  -20999 到 20001 
             p1:  提示信息
    */
    
    create or replace trigger tri_emp_update_sal
    before  
    update
    on emp
    --行级触发器
    for each row
    declare
    
    begin
       if :old.sal > :new.sal  then
          raise_application_error(20001,'亲,不能给员工降薪哦!'); 
       end if;
    end;
    
    
    --测试
    update emp set sal = sal-1 where empno=7369;
    commit;
    
    
    select * from emp;
    
    --创建一个触发器,实现主键自增长
    
    --创建序列:
    create sequence seq_emp_empno;
    
    --创建一个触发器
    create or replace trigger tri_generate_pk
    
    before  --在插入数据之前触发存储函数
    
    insert on emp  --插入数据事件
    
    for each row  --每影响一条记录就会触发一次
    
    begin
      select seq_emp_empno.nextval into :new.empno from dual;
    end;
    --定义一个触发器,删除emp表中数据之前,先备份要删除的数据
    create trigger tri_del_emp
    before    --在删除表中数据之前触发
    delete on emp   --删除事件
    for each row
    begin
      --触发动作,如果删除了数据,那么就进行备份
      insert into emp_bak(empno,ename,sal)
      values(:old.empno,:old.ename,:old.sal);
    end;

    触发器的管理

    --禁用或启动触发器
    alter trigger 触发器 disable|enable;
    
    --禁用或启动表中的所有触发器
    alter table 表名 disable|enable all triggers;
    
    --删除触发器
    drop trigger 触发器;
    展开全文
  • Oracle 触发器

    2020-05-31 15:34:47
    (Insert,update,delete)在指定的表上发出时, Oracle 自动地执行触发器中定义的语句序列。 触发器可用于: 数据确认,实施复杂的安全性检查,做审计,跟踪表上所做的数据操作等,数据的备份和同步 触发器,就是制定...

    一、触发器的基本概念

    数据库触发器是一个与表相关联的、存储的 PL/SQL 程序。每当一个特定的数据操作语句
    (Insert,update,delete)在指定的表上发出时, Oracle 自动地执行触发器中定义的语句序列。

    触发器可用于:
    数据确认,实施复杂的安全性检查,做审计,跟踪表上所做的数据操作等,数据的备份和同步

    触发器,就是制定一个规则,在我们做增删改操作的时候,只要满足该规则,自动触发,无需调用。

    (1)触发器的类型:

    • 语句级触发器 : 在指定的操作语句操作之前或之后执行一次,不管这条语句影响
      了多少行 。
    • 行级触发器(FOR EACH ROW) : 触发语句作用的每一条记录都被触发。在行级触
      发器中使用 old 和 new 伪记录变量, 识别值的状态。
      在这里插入图片描述
    语句级触发器:不包含有for each row的触发器。
    行级触发器:包含有for each row的就是行级触发器。
    加for each row是为了使用:old或者:new对象或者一行记录。
    

    示例:

    • 范例:插入员工后打印一句话“一个新员工插入成功”
      在这里插入图片描述
    • 范例:不能在休息时间插入员工
      在这里插入图片描述
      当执行插入时会报错:
      在这里插入图片描述

    (2)在触发器中触发语句与伪记录变量的值:
    在这里插入图片描述

    • 范例:判断员工涨工资之后的工资的值一定要大于涨工资之前的工资
      在这里插入图片描述
      在这里插入图片描述
    ---语句级触发器
    ----插入一条记录,输出一个新员工入职
    create or replace trigger t1
    after
    insert
    on person
    declare
    
    begin
      dbms_output.put_line('一个新员工入职');
    end;
    ---触发t1
    insert into person values (1, '小红');
    commit;
    select * from person;
    
    ---行级别触发器
    ---不能给员工降薪
    ---raise_application_error(-20001~-20999之间, '错误提示信息');
    create or replace trigger t2
    before
    update
    on emp
    for each row
    declare
    
    begin
      if :old.sal>:new.sal then
         raise_application_error(-20001, '不能给员工降薪');
      end if;
    end;
    ----触发t2
    select * from emp where empno = 7788;
    update emp set sal=sal-1 where empno = 7788;
    commit;
    

    二、触发器实现主键自增

    触发器实现主键自增,这属于行级触发器
    分析:在用户做插入操作的之前,拿到即将插入的数据,给该数据中的主键列赋值。

    ------给该数据中的主键列赋值。
    create or replace trigger auid
    	before
    	insert
    	on person
    	for each row
    declare
    
    begin
    	select s_person.nextval into :new.pid from dual;
    end;
    --查询person表数据
    select * from person;
    ---使用auid实现主键自增
    insert into person (pname) values ('a');
    commit;
    insert into person values (1, 'b');
    commit;
    
    展开全文
  • oracle 触发器

    2018-02-23 09:42:00
    Oracle触发器语法: Create 【or replace】 trigger 触发器名 触发时间 触发事件 On 表名 【for each row 】// 对表的每一行触发器执行一次。如果没有这一选项,则只对整个表执行一次。 Begin Pl/sql 语句 End...

    Oracle触发器语法:

    Create or  replacetrigger 触发器名   触发时间  触发事件

     On 表名

    for each row //  对表的每一行触发器执行一次。如果没有这一选项,则只对整个表执行一次。

    Begin

     Pl/sql 语句

    End

     

     

     

    对If  then     end  if 的理解:

      

    语法格式:
    IF    条件1 THEN
    语句序列1;
    ElSIF 条件2 THEN
    语句序列2;
    [
    ELSIF 条件n THEN
      语句序列 n;
    ]
    [
    ELSE
    语句序列 n+1
    ……
    ]
    END IF;
    
    例:取出7369的薪水,如果薪水<1200,则输出'low',如果<2000则输出'middle',否则'high' 
    --注意elsif的写法,then后面没有分号
    --注意最后一个else后面没有then
    --注意end if后面有一个分号
    
    declare
       v_sal   emp.sal%type;
    begin
       select sal into v_sal from emp where empno = 7369;
       if v_sal < 1200    then
          dbms_output.put_line ('salgrade is low');
       elsif v_sal < 2000 then
          dbms_output.put_line ('salgrade is middle');
       else
          dbms_output.put_line ('salgrade is high');
       end if;
    end;
     

     

     

    下面的触发器在更新表cyq_emp之前触发,目的是不允许在周末修改表:

     

    create or replace trigger auth_secure before insert or update or DELETE

    on cyq_emp

    begin

      IF(to_char(sysdate,'DY')='星期日') THEN

        RAISE_APPLICATION_ERROR(-20600,'不能在周末修改表cyq_emp');

      END IF;

    END;

    使用触发器实现序号自增

    创建一个测试表:

    create table cyq_user(

      id number(11) primary key,

      username varchar(50),

      password varchar(50)

    );

    创建一个序列:

    复制代码 代码如下:

    create sequence my_seq increment by 1 start with 1 nomaxvalue nocycle cache 20;

    创建一个触发器:

    CREATE OR REPLACE TRIGGER MY_TGR

     BEFORE INSERT ON CYQ_USER

     FOR EACH ROW--对表的每一行触发器执行一次

    DECLARE

     NEXT_ID NUMBER;

    BEGIN

     SELECT MY_SEQ.NEXTVAL INTO NEXT_ID FROM DUAL;

     :NEW.ID := NEXT_ID; --:NEW表示新插入的那条记录

    END;

    向表插入数据:

    insert into cyq_user(username,password) values('admin','admin');

    insert into cyq_user(username,password) values('fgz','fgz');

    insert into cyq_user(username,password) values('test','test');

    COMMIT;

    转载于:https://www.cnblogs.com/chaiyingqi/p/8460868.html

    展开全文
  • oracle触发器示例

    2014-02-27 22:06:47
    一个简单的oracle触发器
  • oracle触发器

    2019-09-27 02:51:31
    ORACLE系统里,触发器类似过程和函数,都有声明,执行和异常处理过程的PL/SQL块。  1.说明  1)触发器是一种特殊的存储过程,触发器一般由事件触发并且不能接受参数,存储器由语句块去调用  2)触发器分类: ...
  • oracle触发器功能介绍

    2009-07-28 11:05:34
    oracle触发器功能介绍内附具体说明和简单介绍
  • oracle触发器使用总结

    千次阅读 2018-12-05 12:24:51
    oracle触发器使用总结 1.说明 1)触发器是一种特殊的存储过程,触发器一般由事件触发并且不能接受参数,存储器由语句块去调用 2)触发器分类:  1.DML触发器: 创建在表上,由DML事件引发  2.instead of...
  • ORACLE 触发器

    2018-06-13 10:08:54
    触发器可以看作一种“特殊”的存储过程,它定义了一些与数据库相关事件(如:INSERT 、UPDATE、CREATE等事件)发生时应执行的“功能代码块”,通常用于管理复杂的完整性约束,或监控对表的修改,或通知其他程序,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,030
精华内容 7,212
关键字:

oracle触发器输出