如何检查正在更新的表中的 ref 列的属性 - Oracle

问题描述 投票:0回答:1

我对 Oracle 还很陌生,并且在 REF 方面遇到困难。

我的员工类型具有以下结构:

CREATE TYPE person_type AS OBJECT(
    address at_address_type,
    name at_name_type,
    phones at_nested_phone,
    ni_num VARCHAR2(5)
)NOT FINAL;
/   
CREATE TYPE employee_type UNDER at_person_type(
    emp_id NUMBER,
    supervisor_r REF at_employee_type,  -- NOTE supervisor is a reference to the same type
    job_r REF at_job_type,
    branch_r REF at_branch_type,
    join_date DATE
)FINAL;
/

然后我从employee_type创建一个表:

CREATE TABLE at_employee_table of at_employee_type(
    emp_id PRIMARY KEY,
    
    CONSTRAINT check_emp_address
        CHECK (
            address.street IS NOT NULL
            AND
            address.city IS NOT NULL
            AND
            address.postcode IS NOT NULL
        ),
    CONSTRAINT check_emp_name
        CHECK (
            name.title IS NOT NULL
            AND     
            name.firstname IS NOT NULL
            AND
            name.surname IS NOT NULL
        ),
    CONSTRAINT check_emp_ni CHECK (ni_num IS NOT NULL),
    CONSTRAINT unique_emp_ni UNIQUE (ni_num),
    CONSTRAINT check_emp_job CHECK (job_r IS NOT NULL),
    CONSTRAINT check_emp_branch CHECK (branch_r IS NOT NULL),
    CONSTRAINT check_emp_join CHECK (join_date IS NOT NULL)
)NESTED TABLE phones STORE AS at_nested_emp_phones_storage;
/

我想要做的是检查supervisor_r是否满足以下条件:

supervisor_r.job_r.position IN ('head','manager','team leader') 
AND
supervisor_r.branch_r.branch_code = :NEW.branch_r.branch_code

但是,我似乎无法将其作为约束来执行,因为约束不允许 DEREF,并且我似乎无法使用触发器来执行此操作,因为触发器不允许通过 REF 导航或读取或修改表目前正在修改。由于我是oracle新手,我觉得可能有一些我没有想到的事情可以做。

注意我要求将主管存储为 REF(由于其他原因)。

有人有解决办法吗? 我一直在为这个烦恼。

我已经尝试过约束,并且我已经尝试过触发器,如详细信息中所述。

我试图重新思考我的设计,但我要求将 REF 用于supervisor_r,并且努力想出另一种设计,我可以在其中导航主管(及其主管),仍然使用 REF,同时还强制执行提到的条件。

oracle constraints ref
1个回答
0
投票

我不认为你可以通过约束来做到这一点,但是如果你在 SQL 上下文中取消引用,你可以使用触发器来做到这一点,比如:

CREATE TRIGGER at_employee_trig
BEFORE INSERT ON at_employee_table
FOR EACH ROW
DECLARE
  supervisor_job at_job_type;
  supervisor_branch at_branch_type;
  branch at_branch_type;
BEGIN
  SELECT DEREF(:new.branch_r),
    DEREF(DEREF(:new.supervisor_r).job_r),
    DEREF(DEREF(:new.supervisor_r).branch_r)
  INTO branch, supervisor_job, supervisor_branch
  FROM dual;

  IF supervisor_job.position NOT IN ('head','manager','team leader')  
  OR supervisor_branch.branch_code != branch.branch_code
  THEN
    RAISE_APPLICATION_ERROR(-20001, 'Invalid supervisor');
  END IF;
END;
/

fiddle 显示这个至少可以编译;我还没有创建测试它实际上按您想要的方式运行所需的所有表和数据,但看起来应该......

© www.soinside.com 2019 - 2024. All rights reserved.