提示:触发器简来说就隐式被执行的过程
分类:
CREATE [OR REPLACE] TRIGGER TRIGGER_NAME
{BEFORE|AFTER}
{INSERT|DELETE|UPDATE|[OF COLUMN [,COLUMN..,]]}
OR {INSERT|DELETE|UPDATE|[OF COLUMN [,COLUMN..,]]}
ON [SCHEMA.] TABLE_NAME|[SCHEMA.]VIEW_NAME
[FOR EACH ROW]
[WHEN CONDITION]
BEGIN
TRIGGER_BODY;
END;
--在员工表插入记录前 打印hello world
CREATE TRIGGER MY_TRIGGER1
BEFORE
INSERT --在插入数据时执行触发器
ON SCOTT.EMP --对scott下的emp表进行监视
FOR EACH ROW --行级触发器
BEGIN
DBMS_OUTPUT.PUT_LINE('HELLOWROLD');
END;
--测试触发器
INSERT INTO EMP(EMPNO,ENAME) VALUES(2569,'HAHA');
COMMIT;
代码实现二:为了禁止工作人员在周四周五改变员工信息,(before改变前执行触发器)
-- 为了禁止工作人员在周四周五改变员工信息,(before改变前执行触发器)
CREATE TRIGGER MY_TRIGGER2
BEFORE
INSERT OR UPDATE OR DELETE
ON SCOTT.EMP
FOR EACH ROW --行级触发器
BEGIN
IF TO_CHAR(SYSDATE,'DAY') IN ('星期四','星期五') THEN
--抛出异常 ,提醒不能更新员工信息
RAISE_APPLICATION_ERROR(-1000,'对不起,休息日不能更改员工信息');
END IF;
END;
SELECT to_char(SYSDATE,'DAY') FROM dual;
DELETE FROM EMP WHERE EMPNO=2569;
SELECT * FROM EMP;
代码实现三:对所有员工薪资加1000,并打印旧的薪资和新的薪资
CREATE TRIGGER MY_TRIGGER3
AFTER
UPDATE
ON SCOTT.EMP
FOR EACH ROW --行级触发器
BEGIN
DBMS_OUTPUT.PUT_LINE('HELLOWORLD');
END;
UPDATE EMP SET SAL=SAL+1000;
-- 对所有员工薪资加1000,并打印旧的薪资和新的薪资
CREATE OR REPLACE TRIGGER MY_TRIGGER3
AFTER
UPDATE ON SCOTT.EMP
FOR EACH ROW --行级触发器
BEGIN
--返回旧的薪资:old.sal,新new.sal DBMS_OUTPUT.PUT_LINE('OLD SAL:'||:OLD.SAL||',NEW SAL:'||:NEW.SAL);
END;
UPDATE EMP SET SAL=SAL+1000;
COMMIT;
代码实现四:创建emp备份表(my_emp),编写触发器,在对my_emp数据进行删除的时,在my_emp_bak备份表插入my_emp删除的数据
-- 创建emp备份表(my_emp),编写触发器,在对my_emp数据进行删除的时,在my_emp_bak备份表插入my_emp删除的数据
--创建my_emp表
CREATE TABLE MY_EMP
AS
SELECT EMPNO,ENAME,SAL
FROM EMP;
--查询my_emp表
SELECT * FROM MY_EMP;
--创建my_emp_bak表结构
CREATE TABLE MY_EMP_BAK
AS
SELECT * FROM MY_EMP
WHERE 1=0;
-- 查寻my_emp_bak表
SELECT * FROM MY_EMP_BAK;
SELECT * FROM EMP_1;
DELETE FROM EMP;
COMMIT;
SELECT * FROM EMP;
CREATE TABLE EMP AS SELECT * FROM EMP_1;
CREATE OR REPLACE TRIGGER MY_TRIGGER4
BEFORE
DELETE
ON SCOTT.MY_EMP
FOR EACH ROW --行级触发器
BEGIN
INSERT INTO MY_EMP_BAK VALUES(:OLD.EMPNO,:OLD.ENAME,:OLD.SAL);
--DML 操作无需commit
END;
--测试触发器
DELETE FROM MY_EMP;
COMMIT;
SELECT * FROM MY_EMP;
SELECT * FROM MY_EMP_BAK;
--禁用触发器
ALTER TRIGGER MY_TRIGGER4 DISABLE;
--启用触发器
ALTER TRIGGER MY_TRIGGER4 ENABLE;
--删除触发器
DROP TRIGGER MY_TRIGGER4;
代码实现一:创建触发器,它将映射emp表中每个部门的总人数和总工资
--创建触发器,它将映射emp表中每个部门的总人数和总工资
--首先创建映射表(表的备份将查询结果作为表内容)
CREATE TABLE DEPT_SAL
AS
SELECT DEPTNO,COUNT(EMPNO) TOTAL_EMP,SUM(SAL) TOTAL_SAL
FROM EMP
GROUP BY DEPTNO;
--查看映射表
SELECT * FROM DEPT_SAL;
-- 创建触发器
CREATE OR REPLACE TRIGGER MY_TRIGGER5
AFTER
INSERT OR UPDATE OR DELETE
ON EMP
DECLARE
CURSOR CUR_EMP
IS
SELECT DEPTNO,COUNT(EMPNO) TOTAL_EMP,SUM(SAL) TOTAL_SAL
FROM EMP
GROUP BY DEPTNO;
BEGIN
DELETE DEPT_SAL;
FOR V_EMP IN CUR_EMP LOOP
DBMS_OUTPUT.PUT_LINE(v_emp.deptno || v_emp.total_emp || v_emp.total_sal);
INSERT INTO DEPT_SAL VALUES(V_EMP.DEPTNO,V_EMP.TOTAL_EMP,V_EMP.TOTAL_SAL);
END LOOP;
END;
-- 对emp表进行DML操作
SELECT * FROM EMP;
INSERT INTO emp(empno,deptno,sal) VALUES(123,10,10000);
SELECT * FROM dept_sal;
DELETE EMP WHERE empno=123;
SELECT * FROM dept_sal;
代码实现二:创建触发器,用来记录表删除数据
--创建触发器,用来记录表的删除数据
-- 创建表
CREATE TABLE EMPLOYEE(
ID VARCHAR2(4) NOT NULL,
NAME VARCHAR2(15) NOT NULL,
AGE NUMBER(2) NOT NULL,
SEX CHAR NOT NULL
);
--插入数据
INSERT INTO EMPLOYEE
VALUES('E101','ZHAO',23,'M');
INSERT INTO EMPLOYEE
VALUES('E102','JIAN',21,'F');
COMMIT;
--创建记录表
CREATE TABLE OLD_EMP AS SELECT * FROM EMPLOYEE WHERE 1=0;
--查看表数据
SELECT * FROM EMPLOYEE;
SELECT * FROM OLD_EMP;
-- 创建触发器
CREATE OR REPLACE TRIGGER MY_TIRGGER6
AFTER
DELETE
ON EMPLOYEE
FOR EACH ROW
BEGIN
INSERT INTO OLD_EMP
VALUES(:OLD.ID,:OLD.NAME,:OLD.AGE,:OLD.SEX);
END;
--测试代码
DELETE FROM EMPLOYEE;
SELECT * FROM EMPLOYEE;
SELECT * FROM OLD_EMP;
代码实现三:创建触发器,利用视图插入数据
--创建触发器利用视图插入数据
--创建表
CREATE TABLE tab1 (tid NUMBER(4) PRIMARY KEY,tname VARCHAR2(20),tage NUMBER(2));
CREATE TABLE tab2 (tid NUMBER(4),ttel VARCHAR2(15),tadr VARCHAR2(30));
--插入数据
INSERT INTO tab1 VALUES(101,'zhao',22);
INSERT INTO tab1 VALUES(102,'yang',20);
INSERT INTO tab2 VALUES(101,'13761512841','AnHuiSuZhou');
INSERT INTO tab2 VALUES(102,'13563258514','AnHuiSuZhou');
COMMIT;
--创建视图连接两张表
CREATE OR REPLACE VIEW tab_view AS SELECT tab1.tid,tname,ttel,tadr FROM tab1,tab2 WHERE tab1.tid = tab2.tid;
--创建触发器
CREATE OR REPLACE TRIGGER MY_TRIGGER7
INSTEAD OF
INSERT
ON TAB_VIEW
BEGIN
INSERT INTO TAB1(TID,TNAME) VALUES(:NEW.TID,:NEW.TNAME);
INSERT INTO TAB2(TTEL,TADR) VALUES(:NEW.TTEL,:NEW.TADR);
END;
--测试数据
INSERT INTO tab_view VALUES(106,'ljq','13886681288','beijing');
--查询
SELECT * FROM tab_view;
SELECT * FROM tab1;
SELECT * FROM tab2;
代码实现:创建触发器,比较emp表更新的薪资
--创建触发器 比较emp中更新的工资
CREATE OR REPLACE TRIGGER MY_TRIGGER8
BEFORE
UPDATE
ON EMP
FOR EACH ROW
BEGIN
IF :OLD.SAL>:NEW.SAL THEN
DBMS_OUTPUT.PUT_LINE('工资减少了');
ELSIF :OLD.SAL<:NEW.SAL THEN
DBMS_OUTPUT.PUT_LINE('工资增加了');
ELSE
DBMS_OUTPUT.PUT_LINE('工资没变');
END IF;
DBMS_OUTPUT.PUT_LINE('OLDSAL'||:OLD.SAL);
DBMS_OUTPUT.PUT_LINE('NEW.SAL'||:NEW.SAL);
END;
--测试
UPDATE EMP SET SAL=8000 WHERE EMPNO='7369';
COMMIT;
代码实现:创建触发器,将create、drop 存储在log_info中
--创建触发器 ,将操作create 、drop存储在log_info 表中
CREATE TABLE log_info(
manager_user VARCHAR2(15),
manager_date VARCHAR2(15),
manager_type VARCHAR2(15),
obj_name VARCHAR2(15),
obj_type VARCHAR2(15)
);
-- 创建触发器
CREATE OR REPLACE TRIGGER MY_TRIGGER8
AFTER
CREATE OR DROP
ON SCHEMA
BEGIN
INSERT INTO LOG_INFO
VALUES(USER,SYSDATE,SYS.DICTIONARY_OBJ_NAME,SYS.DICTIONARY_OBJ_OWNER,SYS.DICTIONARY_OBJ_TYPE);
END;
--测试
CREATE TABLE A(ID NUMBER);
CREATE TYPE AA AS OBJECT(ID NUMBER);
DROP TABLE A;
DROP TYPE AA;
--看效果
SELECT * FROM LOG_INFO;
--相关数据字典
SELECT * FROM USER_TRIGGERS;
注意
-在可以在触发器中加⼊:pragma autonomous_transaction;(在DECLARE后⾯) 表⽰是⾃由事务处理。
CREATE OR REPLACE TRIGGER T_create BEFORE insert ON T_Tax_INS_BD
for each row
DECLARE
pragma autonomous_transaction;
NRDSId varchar(500):='';
begin
⼀: 在触发器中使⽤DDL语句。 如 drop table t1 ,触发的时候会报错,
ORA-04092: cannot COMMIT in a trigger,因为DDL语句隐含commit。
⼆: 触发器的主体中使⽤了commit或rollback等DCL语句。ORA-04092:
cannot COMMIT in a trigger , 因为DML(delete/update/insert)触发器中
不能使⽤DDL(CREATE,DROP,ALTER)语句,也不能使⽤事务控制语句(DCL)
(ROLLBACK, COMMIT,SAVEPOINT)。特别注意的是,在触发器的主体中引⽤的
函数(function)/过程(procedure)中也不能有事物控制语句。
三: 注意: 系统级触发器(System Triggers)中可以使⽤DDL语句。
四: 处理⽅法: 去掉事务控制语句;如果procedure中必须有commit,那么可以
将commit 拿掉,由外部控制 。
没有自治事务,在trigger就不能写commit
了解自治事务:转载