Ограничение с помощью триггера - PullRequest
1 голос
/ 17 февраля 2011

Я использую три таблицы - Заказы, Сотрудник и Должность.Заказы имеют Employee_no, а таблица Employee имеет Position_no.Я хочу убедиться, что Employee_Nos в таблице Order - это номера тех сотрудников, которые находятся в Sales.Position_no сотрудников в отделе продаж - 3, 4, 5, 6. Я использовал запрос 1 (см. Ниже), чтобы добавить ограничение проверки.Тем не менее, это не нравится подзапрос.Я мог бы использовать Запрос 2 (см. Ниже), который гарантирует, что таблица Employee_No в Заказах находится в списке (список - это число сотрудников, занятых продажами).Тем не менее, Query 2 не будет работать, если новый сотрудник присоединяется.Я знаю, что это можно решить с помощью триггера, но не знаю как.Буду рад, если кто-нибудь сможет мне помочь.

Ответы [ 3 ]

5 голосов
/ 17 февраля 2011

Я бы не использовал триггеры в вашем случае.С ними трудно иметь дело, и вам нужно знать, как правильно ими управлять.

Рассмотрите следующее решение.

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 и добавляете ограничение, чтобы оно было пустым.

4 голосов
/ 18 февраля 2011

Ах, типы и подтипы.

Сотрудник SALES - это подтип EMP.Предположим, что первичный ключ EMP - EMP_ID.Вы можете создать новый столбец SALES_EMP_ID в EMP и проверочное ограничение, чтобы оно было установлено только там, где сотрудник находится в 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);
0 голосов
/ 17 февраля 2011

Я не часто запускаю триггеры, но в основном это так. Я мог бы иметь синтаксис не совсем правильно.

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...