我使用三张桌子 - 订单,员工和职位。订单有Employee_no,Employee表有Position_no。我想确保Order表中的Employee_Nos是Sales中那些员工的编号。销售中员工的Position_no是3,4,5,6。我使用查询1(见下文)添加检查约束。但是,它不喜欢子查询。我可以使用查询2(见下文),它确保Orders表中的Employee_No在列表中(列表是销售中员工的员工数)。但是,如果新员工加入,则查询2将不起作用。我知道这可以使用触发器解决,但不知道如何。如果有人可以帮助我,我会很高兴的。
答案 0 :(得分:5)
我不会在你的情况下使用触发器。它们很难处理,你需要知道如何正确管理它们。
考虑以下解决方案。
create materialized view check_sales
refresh complete on commit as
select 1 dummy
from ORDERS where
EMPLOYEE_NO IS NOT IN ( SELECT EMPLOYEE_NO FROM EMPLOYEE WHERE POSITION IN (3,4,5,6))
alter table check_sales
add constraint check_sales_empty
check (1=0) deferrable;
我现在没有Oracle来测试我的解决方案,但我认为你有了这个想法。您在check_sales
中选择了错误的订单,并添加了一个应该为空的约束。
答案 1 :(得分:4)
啊,类型和子类型。
SALES员工是EMP的子类型。假设EMP主键是EMP_ID。 您可以在EMP中创建新列SALES_EMP_ID和检查约束,以便仅在雇员处于SALES中时设置它,如果设置,则它必须等于EMP_ID。另一个强制执行唯一性的约束。
然后,您可以创建从ORDERS到EMP.SALES_EMP_ID的参照完整性约束 请参阅以下演示。只有前两个插入T_EMP才会成功 - 其他插入测试检查约束。在T_ORDERS中的插入中,只有第一个(推销员)会成功。
drop table t_emp purge;
CREATE TABLE t_emp
(emp_id number primary key, emp_name varchar2(20),
dept_name varchar2(10),
sales_emp_id number,
constraint sales_emp_id_sales_ck check
((sales_emp_id is null and dept_name != 'SALES') or
(dept_name = 'SALES' and sales_emp_id = emp_id and sales_emp_id is not null)),
constraint sales_emp_id_uk unique (sales_emp_id));
insert into t_emp values (1,'Alan','SALES',1);
insert into t_emp values (2,'Bill','ACCOUNTS',null);
insert into t_emp values (3,'Chuck','ACCOUNTS',3);
insert into t_emp values (4,'Dan','SALES',null);
insert into t_emp values (5,'Ellen','SALES',6);
select * from t_emp;
create table t_orders
(ord_id number primary key,
salesman number,
constraint salesman_fk foreign key (salesman) references t_emp(sales_emp_id));
insert into t_orders values (1,1);
insert into t_orders values (2,2);
答案 2 :(得分:0)
我不经常做触发器,但基本上就是这样。我的语法可能不太正确。
CREATE OR REPLACE TRIGGER check_order_employee_no
ON INSERT INTO orders
BEFORE EACH ROW
AS
match_count INTEGER;
BEGIN
SELECT COUNT(*)
INTO match_count
FROM employee
WHERE employee_no = :new.employee_no
AND position IN (3,4,5,6);
IF match_count = 0 THEN
raise_application_error( -20000, 'Employee # for order must be for a Sales employee' );
END IF;
END check_order_employee_no;