Sea*_*Mci 5 sql oracle entity-relationship
我想使用Orcale SQL开发人员来绘制员工与经理之间的关系。但是,一个经理最多只能监督3名员工。
上面我有一个雇员表,其中经理ID为外键。这与employee表具有一对多关系。
可以将此关系限制为最多3个吗?
谢谢。
这不能通过检查约束来完成。应该可以创建一个物化视图,对每个管理器的出现次数进行计数,并对计数进行检查约束,并在原始表上提交时刷新。正如 Littlefoot 所演示的那样,可以使用复合触发器来实现相同的效果。但这不太可扩展,因为每次提交后都需要扫描整个表以刷新物化视图。
一种替代解决方案是:
创建一个新表来跟踪每个经理出现的次数,例如employee_manager_cnt
在表上设置触发器 employee以保持表employee_manager_cnt最新(无需扫描整个表,只需根据 的新旧值反映更改manager_id)
向 中添加一个检查约束,employee_manager_cnt禁止值高于目标计数
这是一个分步演示,其灵感来自nop77svk 对这个问题的回答
原表:
create table employees (
employee_id number primary key,
manager_id number
);
Run Code Online (Sandbox Code Playgroud)
插入几条记录:
begin
insert into employees values(1, null);
insert into employees values(2, 1);
insert into employees values(3, 1);
insert into employees values(4, 1); -- manager 1 has 3 employees
insert into employees values(5, null);
insert into employees values(6, 5); -- manager 5 has just 1 employee
end;
/
Run Code Online (Sandbox Code Playgroud)
创建新表:
create table employee_manager_cnt (
manager_id number not null primary key,
cnt number(1, 0) not null check (cnt <= 3)
);
Run Code Online (Sandbox Code Playgroud)
填充它:
insert into employee_manager_cnt(manager_id, cnt)
select manager_id, count(*)
from employees
where manager_id is not null
group by manager_id
Run Code Online (Sandbox Code Playgroud)
检查结果:
MANAGER_ID CNT
1 3
5 1
Run Code Online (Sandbox Code Playgroud)
现在,创建触发器:
create or replace trigger trg_employee_manager_cnt
after insert or delete or update of manager_id
on employees
for each row
begin
-- decrease the counter when an employee changes manager or is removed
if updating or deleting then
merge into employee_manager_cnt t
using dual
on ( t.manager_id = :old.manager_id )
when matched then
update set t.cnt = t.cnt - 1
delete where t.cnt = 0
;
end if;
-- increase the counter when a employee changes manager or is added
if inserting or updating then
merge into employee_manager_cnt T
using dual
on ( t.manager_id = :new.manager_id )
when matched then
update set t.cnt = t.cnt + 1
when not matched then
insert (manager_id, cnt) values (:new.manager_id, 1)
;
end if;
end;
/
Run Code Online (Sandbox Code Playgroud)
现在尝试添加一条引用经理 1(已有 3 名员工)的新记录
insert into employees values(4, 1);
-- error: ORA-00001: unique constraint (FIDDLE_QOWWVSAIOXRDGYREFVKM.SYS_C00276396) violated
Run Code Online (Sandbox Code Playgroud)
同时,仍然有可能影响经理 5 的新员工(他只有一名员工):
insert into employees values(10, 5);
-- 1 rows affected
Run Code Online (Sandbox Code Playgroud)