使用触发器的约束

发布于 2024-10-18 05:00:49 字数 298 浏览 4 评论 0原文

我使用三个表 - 订单、员工和职位。 Orders 有 Employee_no,Employee 表有 Position_no。我想确保订单表中的 Employee_Nos 是销售部门的员工编号。 Sales 中员工的 Position_no 为 3, 4, 5, 6。我使用查询 1(见下文)添加检查约束。但是,它不喜欢子查询。我可以使用查询 2(见下文),它确保 Orders 表中的 Employee_No 在列表中(该列表是销售员工的员工编号)。但是,如果有新员工加入,查询 2 将不起作用。我知道可以使用触发器解决这个问题,但不知道如何解决。如果有人能帮助我,我会很高兴。

I am using three tables - Orders, Employee and Position. Orders has Employee_no, and Employee table has Position_no. I want to make sure that the Employee_Nos in Order table are the numbers of those employee who are in Sales. The Position_no of employees in Sales are 3, 4, 5, 6. I used Query 1 (see below) to add a check constraint. However, it doesn't like the subquery. I could use Query 2 (see below) which makes sure that the Employee_No in Orders table is in the list (the list is the employee nos of employees who are in sales). However, Query 2 wouldn't work if a new employee joins. I know this could be solved using a trigger, but not sure how. Would be glad if somebody could help me out.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

鲸落 2024-10-25 05:00:49

在你的情况下我不会使用触发器。它们很难处理,您需要知道如何正确管理它们。

考虑以下解决方案。

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 中选择了不正确的订单,并添加了一个约束,要求其为空。

I wouldn't use triggers in your case. They are difficult to deal with and you need to know how to manage them correctly.

Consider the following solution.

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;

I don't have the Oracle now to test my solution, but I think you got the idea. You select incorrect orders into check_sales and add a constraint that it should be empty.

述情 2024-10-25 05:00:49

啊,类型和子类型。

销售员工是 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);

Ah, types and subtypes.

A SALES employee is a subtype of EMP. Assume the EMP primary key is EMP_ID.
You can create a new column SALES_EMP_ID in EMP and a check constraint so that it is only set where there employee is in SALES and that, if set, it must be equal to EMP_ID. And another constraint to enforce uniqueness.

Then you can create a referential integrity constraint from ORDERS to EMP.SALES_EMP_ID
See the following demo. Only the first two inserts into T_EMP will succeed - the others test the check constraints. Of the inserts into T_ORDERS, only the first (salesman) will succeed.

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);
墨离汐 2024-10-25 05:00:49

我不经常做触发器,但基本上是这样的。我的语法可能不太正确。

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;

I don't do triggers often but it would basically be like this. I might have the syntax not quite right.

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文