Oracle PL/SQL Tutorial/Trigger/Trigger and Transaction

Материал из SQL эксперт
Перейти к: навигация, поиск

Autonomous triggers

   <source lang="sql">

SQL> SQL> SQL> CREATE TABLE order_tab(

 2     order_id     NUMBER(10) PRIMARY KEY,
 3     order_date   DATE NOT NULL,
 4     total_qty    NUMBER,
 5     total_price  NUMBER(15,2),
 6     supp_id      NUMBER(6)
 7  );

Table created. SQL> SQL> CREATE TABLE order_tran_coming_in(

 2     order_id              NUMBER(10)  NOT NULL,
 3     order_date            DATE        NOT NULL,
 4     tran_coming_in_date   DATE        NOT NULL,
 5     success_flag          VARCHAR2(1) DEFAULT "N" NOT NULL);

Table created. SQL> SQL> SQL> SQL> create or replace trigger bi_order_tab

 2  before insert on order_tab for each row
 3  declare
 4    pragma autonomous_transaction;
 5  begin
 6    insert into order_tran_coming_in values (:NEW.order_id,
 7                                             :NEW.order_date,
 8                                             SYSDATE,
 9                                             "N");
10    commit;
11  end;
12  /

Trigger created. SQL> create or replace trigger ai_order_tab

 2  after insert on order_tab for each row
 3  declare
 4    pragma autonomous_transaction;
 5  begin
 6    update order_tran_coming_in
 7    set    success_flag = "Y"
 8    where  order_id = :NEW.order_id;
 9    commit;
10  end;
11  /

Trigger created. SQL> BEGIN

 2    INSERT INTO order_tab VALUES(102,SYSDATE,NULL,NULL,1001);
 3    INSERT INTO order_tab VALUES(103,SYSDATE,NULL,NULL,1001);
 4    INSERT INTO order_tab VALUES(103,SYSDATE,NULL,NULL,1001);
 5  EXCEPTION WHEN DUP_VAL_ON_INDEX THEN
 6    ROLLBACK;
 7  END;
 8  /

PL/SQL procedure successfully completed. SQL> SQL> SQL> drop table order_tran_coming_in; Table dropped. SQL> SQL> drop table order_tab; Table dropped. SQL></source>


Call PRAGMA AUTONOMOUS_TRANSACTION procedure

   <source lang="sql">

SQL> SQL> CREATE TABLE EMP (EMPNO NUMBER(4) NOT NULL,

 2                    ENAME VARCHAR2(10),
 3                    JOB VARCHAR2(9),
 4                    MGR NUMBER(4),
 5                    HIREDATE DATE,
 6                    SAL NUMBER(7, 2),
 7                    COMM NUMBER(7, 2),
 8                    DEPTNO NUMBER(2));

Table created. SQL> SQL> INSERT INTO EMP VALUES (7369, "SMITH", "CLERK", 7902, TO_DATE("17-DEC-1980", "DD-MON-YYYY"), 800, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7499, "ALLEN", "SALESMAN", 7698, TO_DATE("20-FEB-1981", "DD-MON-YYYY"), 1600, 300, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7521, "WARD", "SALESMAN", 7698, TO_DATE("22-FEB-1981", "DD-MON-YYYY"), 1250, 500, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7566, "JONES", "MANAGER", 7839, TO_DATE("2-APR-1981", "DD-MON-YYYY"), 2975, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7654, "MARTIN", "SALESMAN", 7698,TO_DATE("28-SEP-1981", "DD-MON-YYYY"), 1250, 1400, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7698, "BLAKE", "MANAGER", 7839,TO_DATE("1-MAY-1981", "DD-MON-YYYY"), 2850, NULL, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7782, "CLARK", "MANAGER", 7839,TO_DATE("9-JUN-1981", "DD-MON-YYYY"), 2450, NULL, 10); 1 row created. SQL> INSERT INTO EMP VALUES (7788, "SCOTT", "ANALYST", 7566,TO_DATE("09-DEC-1982", "DD-MON-YYYY"), 3000, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7839, "KING", "PRESIDENT", NULL,TO_DATE("17-NOV-1981", "DD-MON-YYYY"), 5000, NULL, 10); 1 row created. SQL> INSERT INTO EMP VALUES (7844, "TURNER", "SALESMAN", 7698,TO_DATE("8-SEP-1981", "DD-MON-YYYY"), 1500, 0, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7876, "ADAMS", "CLERK", 7788,TO_DATE("12-JAN-1983", "DD-MON-YYYY"), 1100, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7900, "JAMES", "CLERK", 7698,TO_DATE("3-DEC-1981", "DD-MON-YYYY"), 950, NULL, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7902, "FORD", "ANALYST", 7566,TO_DATE("3-DEC-1981", "DD-MON-YYYY"), 3000, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7934, "MILLER", "CLERK", 7782,TO_DATE("23-JAN-1982", "DD-MON-YYYY"), 1300, NULL, 10); 1 row created. SQL> SQL> CREATE OR REPLACE PROCEDURE update_salary (dept_in IN NUMBER)

 2  IS
 3     PRAGMA AUTONOMOUS_TRANSACTION;
 4
 5     CURSOR myemps IS
 6        SELECT empno FROM emp
 7         WHERE deptno = dept_in
 8           FOR UPDATE NOWAIT;
 9
10  BEGIN
11     FOR rec IN myemps
12     LOOP
13        UPDATE emp SET sal = sal * 2 WHERE empno = rec.empno;
14     END LOOP;
15     COMMIT;
16  END;
17  /

Procedure created. SQL> SQL> BEGIN

 2     UPDATE emp SET sal = sal * 2;
 3     update_salary (10);
 4  END;
 5  /

BEGIN

ERROR at line 1: ORA-00054: resource busy and acquire with NOWAIT specified ORA-06512: at "sqle.UPDATE_SALARY", line 6 ORA-06512: at "sqle.UPDATE_SALARY", line 11 ORA-06512: at line 3

SQL> SQL> drop table emp; Table dropped. SQL> SQL></source>


Commit in trigger

   <source lang="sql">

SQL> SQL> CREATE TABLE employee_compensation (

 2     company VARCHAR2(100),
 3     NAME VARCHAR2(100),
 4     compensation NUMBER);

Table created. SQL> SQL> CREATE TABLE employee_history (

 2     NAME VARCHAR2(100),
 3     description VARCHAR2(255),
 4     occurred_on DATE);

Table created. SQL> SQL> CREATE OR REPLACE TRIGGER bef_ins_ceo_comp

 2     BEFORE INSERT
 3     ON employee_compensation
 4     FOR EACH ROW
 5  DECLARE
 6     PRAGMA AUTONOMOUS_TRANSACTION;
 7  BEGIN
 8     INSERT INTO employee_history
 9          VALUES (:NEW.NAME, "BEFORE INSERT", SYSDATE);
10
11     COMMIT;
12  END;
13  /

Trigger created. SQL> CREATE OR REPLACE TRIGGER aft_ins_ceo_comp

 2     AFTER INSERT
 3     ON employee_compensation
 4     FOR EACH ROW
 5  DECLARE
 6     PRAGMA AUTONOMOUS_TRANSACTION;
 7  BEGIN
 8     IF :NEW.rupensation > 1000000000
 9     THEN
10        RAISE VALUE_ERROR;
11     ELSE
12        INSERT INTO employee_history VALUES (:NEW.NAME, "AFTER INSERT", SYSDATE);
13        COMMIT;
14     END IF;
15  EXCEPTION
16     WHEN OTHERS
17     THEN
18        ROLLBACK;
19        RAISE;
20  END;
21  /

Trigger created. SQL> COLUMN name FORMAT a20 SQL> COLUMN description FORMAT a30 SQL> SQL> SELECT NAME, description

 2       , TO_CHAR (occurred_on, "MM/DD/YYYY HH:MI:SS") occurred_on
 3    FROM employee_history;

no rows selected SQL> SQL> BEGIN

 2     INSERT INTO employee_compensation VALUES ("B", "J", 9100000);
 3
 4     INSERT INTO employee_compensation VALUES ("B", "A", 10700000);
 5
 6     INSERT INTO employee_compensation VALUES ("B", "Sally Bigdeal", 1000000001);
 7
 8  END;
 9  /

BEGIN

ERROR at line 1: ORA-06502: PL/SQL: numeric or value error ORA-06512: at "sqle.AFT_INS_CEO_COMP", line 15 ORA-04088: error during execution of trigger "sqle.AFT_INS_CEO_COMP" ORA-06512: at line 6

SQL> SQL> SELECT NAME, description

 2         , TO_CHAR (occurred_on, "MM/DD/YYYY HH:MI:SS") occurred_on
 3      FROM employee_history
 4  ORDER BY occurred_on;

NAME DESCRIPTION OCCURRED_ON


------------------------------ -------------------

J BEFORE INSERT 07/24/2008 08:03:16 J AFTER INSERT 07/24/2008 08:03:16 Sally Bigdeal BEFORE INSERT 07/24/2008 08:03:16 A AFTER INSERT 07/24/2008 08:03:16 A BEFORE INSERT 07/24/2008 08:03:16 SQL> SQL> SQL> DROP TABLE employee_compensation; Table dropped. SQL> SQL> DROP TABLE employee_history; Table dropped. SQL></source>


Mark trigger with PRAGMA AUTONOMOUS_TRANSACTION

   <source lang="sql">

SQL> SQL> CREATE TABLE employee_compensation (

 2     company VARCHAR2(100),
 3     name VARCHAR2(100),
 4     compensation NUMBER,
 5     layoffs NUMBER);

Table created. SQL> SQL> SQL> CREATE TABLE employee_history (

 2     name VARCHAR2(100),
 3     description VARCHAR2(255),
 4     occurred_on DATE);

Table created. SQL> SQL> SQL> CREATE OR REPLACE PROCEDURE employee_audit (

 2     name IN VARCHAR2,
 3     description IN VARCHAR2,
 4     occurred_on IN DATE
 5     )
 6  IS
 7     PRAGMA AUTONOMOUS_TRANSACTION;
 8  BEGIN
 9     INSERT INTO employee_history VALUES (
10        employee_audit.name,
11        employee_audit.description,
12        employee_audit.occurred_on
13        );
14
15     IF employee_audit.description LIKE "AFTER%"
16     THEN
17        RAISE VALUE_ERROR;
18     END IF;
19
20     COMMIT;
21  END;
22  /

Procedure created. SQL> CREATE OR REPLACE TRIGGER bef_ins_ceo_comp

 2  BEFORE INSERT ON employee_compensation FOR EACH ROW
 3  DECLARE
 4     ok BOOLEAN := TRUE;
 5  BEGIN
 6     employee_audit (
 7        :new.name, "BEFORE INSERT", SYSDATE);
 8  END;
 9  /

Trigger created. SQL> SQL> CREATE OR REPLACE TRIGGER aft_ins_ceo_comp

 2  AFTER INSERT ON employee_compensation FOR EACH ROW
 3  DECLARE
 4     ok BOOLEAN := FALSE;
 5  BEGIN
 6     employee_audit (
 7        :new.name, "AFTER INSERT", SYSDATE);
 8  END;
 9  /

Trigger created. SQL> SQL> COLUMN name FORMAT a20 SQL> COLUMN description FORMAT a30 SQL> SQL> SELECT name,

 2         description,
 3         TO_CHAR (occurred_on, "MM/DD/YYYY HH:MI:SS") occurred_on
 4    FROM employee_history;

no rows selected SQL> SQL> BEGIN

 2     INSERT INTO employee_compensation VALUES ("M", "J", 9100000, 2700);
 3
 4     INSERT INTO employee_compensation VALUES ("A", "H", 33200000, 3300);
 5
 6     INSERT INTO employee_compensation VALUES ("E", "G", 10700000, 20100);
 7
 8     ROLLBACK; -- I wish!
 9  END;
10  /

BEGIN

ERROR at line 1: ORA-06502: PL/SQL: numeric or value error ORA-06512: at "sqle.EMPLOYEE_AUDIT", line 17 ORA-06512: at "sqle.AFT_INS_CEO_COMP", line 4 ORA-04088: error during execution of trigger "sqle.AFT_INS_CEO_COMP" ORA-06512: at line 2

SQL> SQL> SELECT name,

 2         description,
 3         TO_CHAR (occurred_on, "MM/DD/YYYY HH:MI:SS") occurred_on
 4    FROM employee_history;

NAME DESCRIPTION OCCURRED_ON


------------------------------ -------------------

J BEFORE INSERT 07/24/2008 08:03:13 SQL> SQL> SQL> SQL> SQL> DROP TABLE employee_history; Table dropped. SQL> SQL> DROP TABLE employee_compensation; Table dropped. SQL></source>


SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

   <source lang="sql">

SQL> SQL> CREATE TABLE EMP (EMPNO NUMBER(4) NOT NULL,

 2                    ENAME VARCHAR2(10),
 3                    JOB VARCHAR2(9),
 4                    MGR NUMBER(4),
 5                    HIREDATE DATE,
 6                    SAL NUMBER(7, 2),
 7                    COMM NUMBER(7, 2),
 8                    DEPTNO NUMBER(2));

Table created. SQL> SQL> INSERT INTO EMP VALUES (7369, "SMITH", "CLERK", 7902, TO_DATE("17-DEC-1980", "DD-MON-YYYY"), 800, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7499, "ALLEN", "SALESMAN", 7698, TO_DATE("20-FEB-1981", "DD-MON-YYYY"), 1600, 300, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7521, "WARD", "SALESMAN", 7698, TO_DATE("22-FEB-1981", "DD-MON-YYYY"), 1250, 500, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7566, "JONES", "MANAGER", 7839, TO_DATE("2-APR-1981", "DD-MON-YYYY"), 2975, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7654, "MARTIN", "SALESMAN", 7698,TO_DATE("28-SEP-1981", "DD-MON-YYYY"), 1250, 1400, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7698, "BLAKE", "MANAGER", 7839,TO_DATE("1-MAY-1981", "DD-MON-YYYY"), 2850, NULL, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7782, "CLARK", "MANAGER", 7839,TO_DATE("9-JUN-1981", "DD-MON-YYYY"), 2450, NULL, 10); 1 row created. SQL> INSERT INTO EMP VALUES (7788, "SCOTT", "ANALYST", 7566,TO_DATE("09-DEC-1982", "DD-MON-YYYY"), 3000, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7839, "KING", "PRESIDENT", NULL,TO_DATE("17-NOV-1981", "DD-MON-YYYY"), 5000, NULL, 10); 1 row created. SQL> INSERT INTO EMP VALUES (7844, "TURNER", "SALESMAN", 7698,TO_DATE("8-SEP-1981", "DD-MON-YYYY"), 1500, 0, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7876, "ADAMS", "CLERK", 7788,TO_DATE("12-JAN-1983", "DD-MON-YYYY"), 1100, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7900, "JAMES", "CLERK", 7698,TO_DATE("3-DEC-1981", "DD-MON-YYYY"), 950, NULL, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7902, "FORD", "ANALYST", 7566,TO_DATE("3-DEC-1981", "DD-MON-YYYY"), 3000, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7934, "MILLER", "CLERK", 7782,TO_DATE("23-JAN-1982", "DD-MON-YYYY"), 1300, NULL, 10); 1 row created. SQL> SQL> SQL> SQL> CREATE OR REPLACE PROCEDURE fire_em_all

 2  IS
 3     PRAGMA AUTONOMOUS_TRANSACTION;
 4  BEGIN
 5     DELETE FROM emp;
 6
 7     COMMIT;
 8  EXCEPTION
 9     WHEN OTHERS
10     THEN
11        ROLLBACK;
12  END;
13  /

Procedure created. SQL> SQL> show errors No errors. SQL> SQL> DECLARE

 2     num   INTEGER;
 3  BEGIN
 4     SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
 5
 6     SELECT COUNT (*)
 7       INTO num
 8       FROM emp;
 9
10     DBMS_OUTPUT.put_line ("Before isolated AT delete " || num);
11     fire_em_all;
12
13     SELECT COUNT (*)
14       INTO num
15       FROM emp;
16
17     DBMS_OUTPUT.put_line ("After isolated AT delete " || num);
18     COMMIT; -- ROLLBACK;
19
20     SELECT COUNT (*)
21       INTO num
22       FROM emp;
23
24     DBMS_OUTPUT.put_line ("After MT commit " || num);
25  END;
26  /

PL/SQL procedure successfully completed. SQL> SQL> SQL> drop table emp; Table dropped. SQL> SQL></source>


Transaction with "pragma autonomous_transaction"

   <source lang="sql">

SQL> SQL> CREATE TABLE EMP (EMPNO NUMBER(4) NOT NULL,

 2                    ENAME VARCHAR2(10),
 3                    JOB VARCHAR2(9),
 4                    MGR NUMBER(4),
 5                    HIREDATE DATE,
 6                    SAL NUMBER(7, 2),
 7                    COMM NUMBER(7, 2),
 8                    DEPTNO NUMBER(2));

Table created. SQL> SQL> SQL> INSERT INTO EMP VALUES (7369, "SMITH", "CLERK", 7902, TO_DATE("17-DEC-1980", "DD-MON-YYYY"), 800, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7499, "ALLEN", "SALESMAN", 7698, TO_DATE("20-FEB-1981", "DD-MON-YYYY"), 1600, 300, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7521, "WARD", "SALESMAN", 7698, TO_DATE("22-FEB-1981", "DD-MON-YYYY"), 1250, 500, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7566, "JONES", "MANAGER", 7839, TO_DATE("2-APR-1981", "DD-MON-YYYY"), 2975, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7654, "MARTIN", "SALESMAN", 7698,TO_DATE("28-SEP-1981", "DD-MON-YYYY"), 1250, 1400, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7698, "BLAKE", "MANAGER", 7839,TO_DATE("1-MAY-1981", "DD-MON-YYYY"), 2850, NULL, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7782, "CLARK", "MANAGER", 7839,TO_DATE("9-JUN-1981", "DD-MON-YYYY"), 2450, NULL, 10); 1 row created. SQL> INSERT INTO EMP VALUES (7788, "SCOTT", "ANALYST", 7566,TO_DATE("09-DEC-1982", "DD-MON-YYYY"), 3000, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7839, "KING", "PRESIDENT", NULL,TO_DATE("17-NOV-1981", "DD-MON-YYYY"), 5000, NULL, 10); 1 row created. SQL> INSERT INTO EMP VALUES (7844, "TURNER", "SALESMAN", 7698,TO_DATE("8-SEP-1981", "DD-MON-YYYY"), 1500, 0, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7876, "ADAMS", "CLERK", 7788,TO_DATE("12-JAN-1983", "DD-MON-YYYY"), 1100, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7900, "JAMES", "CLERK", 7698,TO_DATE("3-DEC-1981", "DD-MON-YYYY"), 950, NULL, 30); 1 row created. SQL> INSERT INTO EMP VALUES (7902, "FORD", "ANALYST", 7566,TO_DATE("3-DEC-1981", "DD-MON-YYYY"), 3000, NULL, 20); 1 row created. SQL> INSERT INTO EMP VALUES (7934, "MILLER", "CLERK", 7782,TO_DATE("23-JAN-1982", "DD-MON-YYYY"), 1300, NULL, 10); 1 row created. SQL> SQL> create or replace procedure child

 2  as
 3          pragma autonomous_transaction;
 4          l_ename emp.ename%type;
 5  begin
 6
 7      update emp set ename = "y" where ename = "BLAKE";
 8      rollback to Parent_Savepoint;
 9      commit;
10  end;
11  /

Procedure created. SQL> SQL> create or replace procedure parent

 2  as
 3          l_ename emp.ename%type;
 4  begin
 5      savepoint Parent_Savepoint;
 6      update emp set ename = "x" where ename = "KING";
 7
 8      child;
 9      rollback;
10  end;
11  /

Procedure created. SQL> SQL> exec parent BEGIN parent; END;

ERROR at line 1: ORA-01086: savepoint "PARENT_SAVEPOINT" never established ORA-06512: at "sqle.CHILD", line 8 ORA-06512: at "sqle.PARENT", line 8 ORA-06512: at line 1

SQL> SQL> SQL> drop table emp; Table dropped. SQL></source>