如何在PL / SQL中编写语句级触发器

时间:2018-05-21 03:30:35

标签: sql oracle plsql triggers

CREATE TABLE faculty
(f_id NUMBER(6),
f_last VARCHAR2(15),
f_first VARCHAR2(15),
f_mi CHAR(1),
loc_id NUMBER(5) not null,
f_phone VARCHAR2(10),
f_rank VARCHAR2(9),
f_salary number(9,2), 
f_super NUMBER(6), --supervisor/manager of the faculty member
f_pin NUMBER(4),
f_image BLOB, 
CONSTRAINT faculty_f_id_pk PRIMARY KEY(f_id),
CONSTRAINT faculty_loc_id_fk FOREIGN KEY (loc_id) REFERENCES location(loc_id));

--- inserting records into FACULTY
INSERT INTO faculty VALUES
(1, 'Marx', 'Teresa', 'J', 9, '4075921695', 'Associate', 75000.00, 4, 6338, EMPTY_BLOB());

INSERT INTO faculty VALUES
(2, 'Zhulin', 'Mark', 'M', 10, '4073875682', 'Full', 98000.00, NULL, 1121, EMPTY_BLOB());

INSERT INTO faculty VALUES
(3, 'Langley', 'Colin', 'A', 12, '4075928719', 'Assistant', 60000.00, 4, 9871, EMPTY_BLOB());

INSERT INTO faculty VALUES
(4, 'Brown', 'Jonnel', 'D', 11, '4078101155', 'Full', 102000.00, NULL, 8297, EMPTY_BLOB());

INSERT INTO faculty VALUES
(5, 'Sealy', 'James', 'L', 13, '4079817153', 'Associate', 80000.00, 1, 6089, EMPTY_BLOB());

我已经写过这个ROW Level触发器(在下面),但是不知道如何获得一个声明级触发器,它可以做同样的事情。并且因为不能使用:NEW / :OLD在语句级别,然后混淆......

--Row Level
create or replace TRIGGER TRG_F_SALARY_CHECK
BEFORE INSERT OR UPDATE OF F_SUPER ON FACULTY
FOR EACH ROW

BEGIN
    IF :NEW.F_SUPER > :OLD.F_SUPER THEN
        :NEW.F_SALARY := :OLD.F_SALARY + 2000*(:NEW.F_SUPER - 5);
        DBMS_OUTPUT.PUT_LINE('The salary has been updated');
    END IF;
    IF :NEW.F_SUPER < :OLD.F_SUPER THEN
        IF :OLD.F_SUPER >=5 THEN
            IF :NEW.F_SUPER < 5 THEN
                :NEW.F_SALARY := :OLD.F_SALARY - 2000*(:OLD.F_SUPER - 5);
                DBMS_OUTPUT.PUT_LINE('The salary has been updated');
            ELSE
              :NEW.F_SALARY := :OLD.F_SALARY - 2000*(:OLD.F_SUPER - :NEW.F_SUPER);
              DBMS_OUTPUT.PUT_LINE('The salary has been updated');
            END IF;
        END IF;
    END IF;
END;

create or replace TRIGGER TRG_F_SALARY_CHECK_STATEMENT
BEFORE INSERT OR UPDATE OF F_SUPER, F_SALARY ON FACULTY
DECLARE
  --  OLD_F_SUPER NUMBER(10);
    OLD_F_SALARY NUMBER(9);
BEGIN
--        SELECT F_SUPER INTO OLD_F_SUPER FROM FACULTY;
--       SELECT SUM(F_SALARY) INTO OLD_F_SALARY FROM FACULTY
--       WHERE F_ID;
   UPDATE FACULTY
   /* SET F_SALARY = F_SALARY + 2000*(F_SUPER -5)
        WHERE F_SUPER > 5;*/
        SET F_SALARY = OLD_F_SALARY + 2000*(F_SUPER - 5)
            WHERE F_SUPER > 5;
END;

顺便说一句,表FACULTY包括F_IDF_SALARYF_SUPER等。我将获得**单行触发**(已经完成)和一个语句触发器,用于更改F_SUPER号码更改的教师工资。 对于5之后的每次F_SUPER更改(增加或减少),F_SALARY将更改(增加或减少)$ 2000。

测试代码如下:

/*F_ID = 5, F_SUPER = 7, F_SALARY = 84000*/
UPDATE FACULTY
SET F_SUPER = 7
WHERE F_ID = 5;
/*F_ID =5, F_SUPER = 2, F_SALARY = 80000*/ 
UPDATE FACULTY
SET F_SUPER = 2
WHERE F_ID = 5;

由于

2 个答案:

答案 0 :(得分:1)

  

我已经写过这个ROW Level触发器(下面),但不知道怎么做   获得一个语句级触发器,它可以做同样的事情   这个。而且因为不能使用:NEW /:OLD在语句级别,然后   困惑...

语句级触发器和行级触发器不相同。它们由Oracle提供,具体取决于用法。因此,所有行级触发器都不能用语句级触发器替换。见下面的定义和用法:

与数据相关的活动的行级触发器

  

•行级触发器对事务中的每一行执行一次。

     

•行级触发器是最常见的触发器类型;他们是   经常用于数据审计应用程序。

     

•行级触发器由FOR EACH ROW子句标识   CREATE TRIGGER命令。

与交易相关的活动的声明级触发器

  

•语句级触发器为每个事务执行一次。对于   例如,如果单个事务在Customer中插入500行   table,那个表上的语句级触发器只会是   执行一次。

     

•因此通常不会使用语句级触发器   与数据有关的活动;它们通常用于强制执行额外的操作   对可能执行的交易类型的安全措施   在桌子上。

     

•语句级触发器是创建的默认触发器类型   并通过省略CREATE中的FOR EACH ROW子句来识别   TRIGGER命令。

语句级别触发器示例:

CREATE or REPLACE TRIGGER Before_Update_Stat_product 
BEFORE UPDATE ON product 
Begin 
  INSERT INTO table  
  Values('Before update, statement level',sysdate); 
END; 
/ 

答案 1 :(得分:0)

他希望使用语句级触发器来更新整个表(带过滤器),并且IMO的触发器应该是“在插入或更新后”。