Какой правильный прототип для моего SQL кода? - PullRequest
0 голосов
/ 21 апреля 2020

Я новичок в изучении SQL и пытаюсь применить триггер к этим двум таблицам с помощью SQLcl:

prodc

(PRODC_NAME, DISCOUNTED CHAR (1) DEFAULT 'N ', PK PRIMARY KEY (PRODC_NAME));

peopleOrder
(  ORDERID, PRODC_NAME,
   PRIMARY KEY (ORDERID, PRODC_NAME),
   FOREIGN KEY (PRODC_NAME) REFERENCES PRODC (PRODC_NAME));

Я хочу, чтобы мой триг сделал следующее:

, когда я обновляю или вставляю строки в peopleOrder, триг следует проверить, имеет ли строка product_name значение 'N' в столбце со скидкой, который находится в таблице product; если у него нет значения 'N', должно появиться сообщение об ошибке.

Я пробовал много способов и следующий триггер, но когда я вставляю строки, триггер, кажется, не работает и не влияет на строки:

CREATE OR REPLACE TRIGGER constraint_1
After UPDATE OR INSERT on peopleOrder 
for each row
begin
    if not (:new.prodc_name in 
    (select prodc_name from prodc where discounted = 'N' )) then
     RAISE_ERROR(-30001, 'No product can be ordered 
 !');
    END IF; 
    INSERT INTO peopleOrder  VALUES (:new.ORDERID, :new.PRODC_NAME);
END; 
/

Моя команда вставки:

INSERT INTO peopleOder (ORDERID, PRODC_NAME) 
VALUES (251, 'Puton'); 

, а 'Puton' имеет значение 'N' в столбце со скидкой в ​​таблице prod c.

1 Ответ

0 голосов
/ 21 апреля 2020

Первое, что вам нужно, это понять, что такое триггер. Это кусок кода, который запускается как часть оператора, вызывающего его срабатывание. По этой причине вы не можете ссылаться на таблицу, вызывая ее срабатывание. Обычно это совершенно не нужно в любом случае. Каждый триггер строки имеет доступ к 2 строкам: копия существующих данных (старые) и результирующие данные (новые). Обновите, заполнив и вставив / удалив только новое / старое, в зависимости от действия. Триггеры до того, как оператор может изменить новые данные, после триггеров не могут. Эти строки позволяют обрабатывать столбцы в таблице без DML или выбирать их. (Однако вы не можете «сканировать» таблицу). На любом уровне триггер может вызвать исключение, которое останавливает весь процесс и оператор вызова. Если исключение не возникает, обработка вызова продолжается. Для более полного описания см. PL / SQL Справочник по языку или версию Oracle, которую вы используете. В этом случае ваш триггер разбивается на один оператор if.

-- Revised. Orig missed that flag comming from different table.

    create or replace trigger constraint_1
    before update or insert on peopleOrder 
    for each row
    declare 
        dis_num integer; 
    begin  
        select count(*)
          into dis_num
          from product 
         where discounted != 'N'
           and product_name = :new.product_name
           and rownum < 2; 
        if dis_num != 0 then 
           raise_application_error(-20001, 'No discounted product can be ordered!');
        end if; 
    end constraint_1;



-- Orig ==============================================
    CREATE OR REPLACE TRIGGER constraint_1
    before UPDATE OR INSERT on peopleOrder 
    for each row
    begin
        if :new.discounted = 'N' then
         RAISE_APPLICATION_ERROR(-20001, 'No discounted product can be ordered')
        end if; 
    END; 
    /  
...