Как получить дату из двух таблиц с помощью триггера перед вставкой в ​​​​третью таблицу?

Я пытаюсь создать триггер TrgDisAmount для чтения PROD_NAME и PRICE из таблицы PRODUCT и для вычисления DISCOUNT и AMOUNT таблицы SALES для каждой новой вставленной строки со значениями SERIAL и PCODE.

Это информация о таблицах

Table SALES (SERIAL, PCODE, PROD_NAME, PRICE, DISCOUNT, AMOUNT)

Table PRODUCT (PCODE, PROD_NAME, PROD_CAT, PRICE)

Table DISCOUNT (PROD_CAT, DISCOUNT_RATE)

Примечание.

  1. Введите значения только для SERIAL и PCODE, остальные столбцы должны вводиться только триггером TrgDisAmount
  2. Получите DISCOUNT_RATE с помощью функции GetDiscount.

Я уже создал функцию GetDiscount для получения DISCOUNT_RATE из таблицы DISCOUNT.

Это моя попытка:

create or replace trigger TrgDisAmount
  before insert on SALES for each row
begin
  if :new.PCODE = :old.PRODUCT.PCODE then

    :new.PROD_NAME := :old.PRODUCT.PROD_NAME;
    :new.PRICE := :old.PRODUCT.PRICE;
    :new.DISCOUNT := :old.product.PRICE / (GetDiscount(:old.PRODUCT.PROD_CAT));
    :new.AMOUNT := :new.PRICE - :new.DISCOUNT;
  end if;

  insert into SALES columns (PROD_NAME, PRICE, DISCOUNT, AMOUNT) 
  values (:new.PROD_NAME, :new.PRICE, :new.DISCOUNT, :new.AMOUNT);
end;
/

Когда я запускаю этот блок, он показывает мне эту ошибку:

PLS-00049: bad bind variable 'OLD.PRODUCT'

Я использую Table_Name.Column_name для доступа к определенному столбцу. Законно ли это делать?


Пример вывода должен быть таким:

SQL> insert into sales values (1,'MB-101',null, null, null, null);

Result in SALES table:
   SERIAL : 1,
   PCODE : MB-101,
   PROD_NAME : IPHONE 6+,
   PRICE : 250 ,
   DISCOUNT : 25,
   AMOUNT : 225

person user125150    schedule 20.06.2015    source источник
comment
В чем проблема с вашим кодом? Выдает ошибку? Он делает что-то не так?   -  person Gordon Linoff    schedule 20.06.2015
comment
Когда я запускаю этот блок, он показывает мне ошибку: PLS-00049: неверная переменная связывания «OLD.PRODUCT» @GordonLinoff   -  person user125150    schedule 20.06.2015
comment
Исправьте эти ошибки: 1. Удалите: OLD 2. Правильно вызовите свою функцию и 3. Удалите предложение INSERT INTO. Для триггера «Перед вставкой» инструкция INSERT не требуется, при совпадении условия строка вставляется автоматически. Фрагмент кода ниже @user125150   -  person mahi_0707    schedule 21.06.2015


Ответы (2)


Когда вы создаете триггер before insert, вам нужно только установить :new значения. Вы на самом деле не вставляете в таблицу. Это следующий шаг в обработке.

Кроме того, в триггере insert ссылайтесь только на значения :new, а не на :old. Нет значения :old, которое является конкретной ошибкой, которую вы получаете.

Затем вам нужно выполнить запрос, чтобы получить соответствующую информацию из других таблиц. Результат должен выглядеть примерно так:

create or replace trigger TrgDisAmount
before insert on SALES
for each row
begin
    select p.price / d.discount into :new.discount
    from product p join
         discount d
         on p.prod_cat = d.prod_cat
    where :new.pcode = p.pcode;
    :new.AMOUNT := :new.PRICE - :new.DISCOUNT;
end;

Очень подозрительно выглядит арифметика определения скидки. Скидка 10% будет представлена ​​как 1,11, если использовать эту методологию. Однако это арифметика в вашем вопросе, и вы не предоставляете образцы данных, чтобы предложить какой-либо другой метод.

person Gordon Linoff    schedule 20.06.2015
comment
как я могу получить данные из других таблиц? см. часть обновления в вопросе, оператор SQL и его результат @GordonLinoff - person user125150; 21.06.2015
comment
@ пользователь125150 . . . Этот запрос правильно использует SELECT для получения данных из других таблиц. - person Gordon Linoff; 21.06.2015

Можете ли вы попробовать изменить способ, которым вы вызываете свою функцию.

Как упомянул Гордон, в этом случае нельзя использовать :old.

CREATE or replace trigger TrgDisAmount 
Before insert 
on SALES 
for each row 

DECLARE
v_prod_cat varchar2(20);

BEGIN 

select PROD_NAME into :NEW.PROD_NAME
from PRODUCT 
where PRODUCT.PCODE = :NEW.PCODE;  

select  PRICE into :NEW.PRICE 
from PRODUCT 
where PRODUCT.PCODE = :NEW.PCODE; 

select  PROD_CAT into v_prod_cat from discount where  PROD_CAT 
in( select PROD_CAT from PRODUCT where  PCODE = :NEW.PCODE); 

select  GetDiscount(v_prod_cat) into :NEW.discount from dual;

 :new.AMOUNT := :new.PRICE - :new.DISCOUNT;

END;
/

Trigger created.   
SQL> show err;                                                        
 No errors.

insert into sales  values(701,1,NULL,NULL,NULL,NULL);

введите здесь описание изображения

person mahi_0707    schedule 20.06.2015
comment
см. часть обновления в вопросе @mahendar-mahi - person user125150; 21.06.2015
comment
@ user125150 Вы пробовали так? - person mahi_0707; 22.06.2015