用于范围检查的 Oracle 验证触发器

Oracle Validation Trigger for range check

可能有人问过类似的问题,如果是,请分享 link。

必填:

每当创建或更新新记录时,都需要验证此人的薪水是否在工作范围内。

下面是触发器,

create or replace TRIGGER secure_employees_sal_range
  BEFORE INSERT OR UPDATE OF salary,job_id ON employees
FOR EACH ROW
DECLARE
p_min_sal Integer;
p_max_sal Integer;
BEGIN
  --check_salaray_range(employee_id,job_id,salary);

  select min_salary, max_salary
  into p_min_sal, p_max_sal
  from jobs
  where job_id = p_job_id;

  if p_salary < p_min_sal OR p_salary > p_max_sal THEN
  RAISE_APPLICATION_ERROR (-20225,
        'Salray should in range' || p_min_sal || ' and ' || p_max_sal);
  END IF;

END secure_employees_sal_range;

但我收到错误

Error at line 13: PL/SQL: Statement ignored

 Line 14: where job_id = :new.job_id;

我们如何设置员工 table 的 p_job_id 的值?

更新: 现在在创建新员工时在工资超出范围时收到错误消息

ORA-20225: Salray should in range4000 and 10000 ORA-06512: at "HR.SECURE_EMPLOYEES_SAL_RANGE", line 14 ORA-04088: error during execution of trigger 'HR.SECURE_EMPLOYEES_SAL_RANGE' Unable to process row of table EMPLOYEES.

然后在尝试更新现有记录时,

ORA-20505: Error in DML: p_rowid=215, p_alt_rowid=EMPLOYEE_ID, p_rowid2=, p_alt_rowid2=. ORA-20225: Salray should in range4000 and 10000 ORA-06512: at "HR.SECURE_EMPLOYEES_SAL_RANGE", line 14 ORA-04088: error during execution of trigger 'HR.SECURE_EMPLOYEES_SAL_RANGE' Unable to process row of table EMPLOYEES.

触发器没有参数。

我的猜测是您需要行级触发器,而不是此处的语句级触发器。我猜想在行级触发器中,您想使用 :new.job_id 来查找 jobs table

中的数据
create or replace TRIGGER secure_employees_sal_range
  BEFORE INSERT OR UPDATE OF salary,job_id ON employees
  FOR EACH ROW
DECLARE
  p_min_sal Integer;
  p_max_sal Integer;
BEGIN
  --check_salaray_range(employee_id,job_id,salary);

  select min_salary, max_salary
    into p_min_sal, p_max_sal
    from jobs
   where job_id = :new.job_id;

  if p_salary < p_min_sal OR p_salary > p_max_sal THEN
    RAISE_APPLICATION_ERROR (-20225,
        'Salary should in range' || p_min_sal || ' and ' || p_max_sal);
  END IF;
END secure_employees_sal_range;

我假设这是一项家庭作业。实际上,在多用户系统中,这种触发器存在多种问题。例如,有人可能在您修改 employees table 的同时修改 jobs table,并且两个事务都无法看到未提交的工作另一个。即使您在 jobs 上有相应的触发器,也完全有可能以违反您试图执行的范围规则的保存数据结束。

作为一般规则,我还建议局部变量使用 l_ 前缀而不是通常表示参数的 p_。我通常也会建议您使用锚定类型。所以

l_min_sal jobs.min_salary%type;

这样,如果 jobs table 中的数据类型发生变化,您的代码会自动适应。