DML触发器连续

时间:2012-11-11 21:44:07

标签: sql database oracle plsql triggers

我试图写一个触发器“restrict_salary”,它禁止向既不是总统也不是经理的员工颁发超过10,000美元的薪水。 如果“更新”不影响列“sal”,则不应触发触发器。在此之后,考虑使触发器禁止也增加超过9%。我尝试了一些东西但是我被卡住了,这是我的代码。

CREATE OR REPLACE TRIGGER restrict_salary
BEFORE
UPDATE OF sal
ON EMP
REFERENCING emp AS new_emp
FOR EACH ROW
WHEN (sal > 10000)
BEGIN
DECLARE job VARCHAR2(30);
    select job into job from ename;
    IF job!='MANAGER' OR job != 'PRESIDENT' THEN
        raise_application_error (-20002, 'Cannot attribute more than 10000 dollars ');
    END IF;

END;
/

1 个答案:

答案 0 :(得分:3)

您的begindeclare方向错误。您必须在开始PL / SQL块之前声明变量。

我还将before update of sal on emp更改为before update on emp并将new.添加到WHEN子句中,因为这是必需的。

CREATE OR REPLACE TRIGGER restrict_salary
BEFORE UPDATE ON EMP
FOR EACH ROW
WHEN (new.sal > 10000)
DECLARE 
   job ename.job%type;
BEGIN
    -- THERE WAS A MISSING WHERE CLAUSE!!!
   select job into job from ename where empid = :new.id;

   IF job not in ('MANAGER', 'PRESIDENT') THEN
      raise_application_error (-20002, 'Error that fit''s on page');
   END IF;

END restrict_salary;
/

最大的问题是select into ...缺少WHERE子句。这意味着如果此表中有多行,则总是会出现TOO_MANY_ROWS错误。我已经改变了,你可以看到,但你可能需要再次更改它,具体取决于你的架构。

为了清楚起见,我已将触发器的名称添加到end语句中,并删除了不必要的referencing子句。这两者都没有必要使其工作,但有助于提高可读性。

最后,我已将变量job声明为您获取它的列的类型。这使您可以更改表中的列,而不会影响触发器。总是声明依赖于这样的表的变量是明智的,因为它大大减少了数据库中的更改导致的错误数量,并大大减少了代码库中的混淆。

我强烈建议您阅读the documentation以了解语法。