使用从相同 table 获取值的变量创建更新触发器的正确方法是什么?
What is the proper way to create an update trigger with a variable getting value from the same table?
我正在创建一个更新触发器,其中员工的薪水永远不会高于总裁的薪水。但是我需要子查询总裁的薪水进行比较,"new" 更新了员工的薪水。
我最初使用来自员工 table 的子查询,但由于变异 table 问题不得不创建一个新的 table。我不认为创建一个新的 table 是真正实现的合理解决方案。
有没有什么办法可以在不创建新的table的情况下节省总裁的薪水?
CREATE OR REPLACE TRIGGER prevent_salary
BEFORE UPDATE ON employees
FOR EACH ROW
declare pres_sal number(8,2);
BEGIN
select salary into pres_sal from employees_salary where job_id='AD_PRES';--employees_salary was employees but that gives mutating error
IF (:new.salary > pres_sal)
THEN UPDATE employees
SET salary = :old.salary
WHERE employee_id = :old.employee_id;
END IF;
END;
你可以试试这个:
CREATE OR REPLACE TRIGGER prevent_salary
BEFORE UPDATE ON employees
FOR EACH ROW
declare pres_sal number(8,2);
BEGIN
select salary into pres_sal from employees_salary where job_id='AD_PRES';--employees_salary was employees but that gives mutating error
IF (:new.salary > pres_sal)
Raise_Application_Error (-20101, 'An employee''s salary couldn''t exceed president''s !');
END IF;
END;
一种方法是在 BEFORE STATEMENT
触发器中保存总裁的薪水,然后在 FOR EACH ROW
触发器中使用它。
"Compound Triggers",至少从 11.1 版开始就存在,提供了一种在一个地方完成所有操作的好方法。
这是一个例子:
CREATE OR REPLACE TRIGGER prevent_salary
FOR UPDATE OF salary ON employees
COMPOUND TRIGGER
pres_sal NUMBER;
BEFORE STATEMENT IS
BEGIN
select salary
into pres_sal
from employees
where job_id='AD_PRES';
END BEFORE STATEMENT;
BEFORE EACH ROW IS
BEGIN
:new.salary := least(:new.salary, pres_sal);
END BEFORE EACH ROW;
END prevent_salary;
我正在创建一个更新触发器,其中员工的薪水永远不会高于总裁的薪水。但是我需要子查询总裁的薪水进行比较,"new" 更新了员工的薪水。
我最初使用来自员工 table 的子查询,但由于变异 table 问题不得不创建一个新的 table。我不认为创建一个新的 table 是真正实现的合理解决方案。
有没有什么办法可以在不创建新的table的情况下节省总裁的薪水?
CREATE OR REPLACE TRIGGER prevent_salary
BEFORE UPDATE ON employees
FOR EACH ROW
declare pres_sal number(8,2);
BEGIN
select salary into pres_sal from employees_salary where job_id='AD_PRES';--employees_salary was employees but that gives mutating error
IF (:new.salary > pres_sal)
THEN UPDATE employees
SET salary = :old.salary
WHERE employee_id = :old.employee_id;
END IF;
END;
你可以试试这个:
CREATE OR REPLACE TRIGGER prevent_salary
BEFORE UPDATE ON employees
FOR EACH ROW
declare pres_sal number(8,2);
BEGIN
select salary into pres_sal from employees_salary where job_id='AD_PRES';--employees_salary was employees but that gives mutating error
IF (:new.salary > pres_sal)
Raise_Application_Error (-20101, 'An employee''s salary couldn''t exceed president''s !');
END IF;
END;
一种方法是在 BEFORE STATEMENT
触发器中保存总裁的薪水,然后在 FOR EACH ROW
触发器中使用它。
"Compound Triggers",至少从 11.1 版开始就存在,提供了一种在一个地方完成所有操作的好方法。
这是一个例子:
CREATE OR REPLACE TRIGGER prevent_salary
FOR UPDATE OF salary ON employees
COMPOUND TRIGGER
pres_sal NUMBER;
BEFORE STATEMENT IS
BEGIN
select salary
into pres_sal
from employees
where job_id='AD_PRES';
END BEFORE STATEMENT;
BEFORE EACH ROW IS
BEGIN
:new.salary := least(:new.salary, pres_sal);
END BEFORE EACH ROW;
END prevent_salary;