我想编写一个触发器来阻止从表中删除记录并阻止更新时的工资减少。它可以作为两个单独的触发器,但我想将它合并为一个。
以下是合并后的触发器:
CREATE OR REPLACE TRIGGER test
BEFORE DELETE OR UPDATE
ON emp
FOR EACH ROW
BEGIN
IF UPDATING THEN
IF :NEW.sal < :OLD.sal THEN
raise_application_error(-20500, 'You cannot decrease emp salary');
END IF;
ELSE DELETING THEN
raise_application_error(-20500, 'You cannot delete records from emp');
END IF;
END;
问题是当我尝试更新或删除记录时出现错误:
04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation"
*Cause: A trigger was attempted to be retrieved for execution and was
found to be invalid. This also means that compilation/authorization
failed for the trigger
我认为这一行有一个问题 - BEFORE DELETE OR UPDATE
因为据我所知,我应该写FOR EACH ROW
一句是BEFORE UPDATE on sal
,但我不知道知道如何将BEFORE DELETE
声明加入此内容。
编辑:
问题出在ELSE
附近。它应该更改为ELSIF
答案 0 :(得分:2)
您的IF语句语法不正确。它应该是:
CREATE OR REPLACE TRIGGER test
BEFORE DELETE OR UPDATE
ON emp
FOR EACH ROW
BEGIN
IF UPDATING AND :NEW.sal < :OLD.sal THEN
raise_application_error(-20500, 'You cannot decrease emp salary');
ELSIF DELETING THEN
raise_application_error(-20500, 'You cannot delete records from emp');
END IF;
END test;
我还将UPDATING案例中使用的两个IF语句合并为一个,以使其更简单。
修改强>
如果您不想让工资减少,另一种可能的解决办法是将工资悄然改回原来的价值,如:
CREATE OR REPLACE TRIGGER test
BEFORE DELETE OR UPDATE
ON emp
FOR EACH ROW
BEGIN
IF UPDATING AND :NEW.sal < :OLD.sal THEN
:NEW.sal := :OLD.sal; -- restore original salary
ELSIF DELETING THEN
raise_application_error(-20500, 'You cannot delete records from emp');
END IF;
END test;