Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Oracle > Триггеры и первичные ключи


Автор: mgukov 27.12.2009, 19:41
Есть 2 таблице - ЗАКАЗ и ВЫДАЧА, как показано на рисунке. Ключевое поле одной таблицы является ключевым и внешним полем другой таблицы. Мне нужен триггер который при вставке строки в первую таблицу, добавляет строку во вторую. Проблема с первичным ключем. Подскажите как можно реализовать такой триггер?

Автор: v2v 27.12.2009, 23:35
если я правильно понял, то триггер должен выглядеть следующим образом:
Код



    CREATE OR REPLACE TRIGGER после_вставки_заказа
    AFTER INSERT
        ON ЗАКАЗЫ
        FOR EACH ROW

    DECLARE

    BEGIN

        INSERT INTO ВЫДАЧА
         ( ид_заказа,
           дата )
        VALUES
         ( :new.ид_заказа,
            sysdate);

    END;


Автор: mgukov 28.12.2009, 00:10
Именно так я и делал, однако возникает ошибка:
Error starting at line 4 in command:
INSERT INTO ЗАКАЗ VALUES(100, 'не оплачен', NULL, 100, 104)
Error report:
SQL Error: ORA-02291: integrity constraint (USER1.RELATION_6) violated - parent key not found
ORA-06512: at "USER1.TIA_ЗАКАЗ", line 2
ORA-04088: error during execution of trigger 'USER1.TIA_ЗАКАЗ'
02291. 00000 - "integrity constraint (%s.%s) violated - parent key not found"
*Cause:    A foreign key value has no matching primary key value.
*Action:   Delete the foreign key or add a matching primary key.

Так как в таблице ВЫДАЧА поле заказ_ид является внешним ключем, то при добавлении в нее новой записи с :new.заказ_ид, oracle пытается найти это значение в таблице ЗАКАЗ, но этого (:new.заказ_ид) значения там еще нет.

Автор: Zloxa 28.12.2009, 01:26
Цитата(mgukov @  28.12.2009,  00:10 Найти цитируемый пост)
но этого (:new.заказ_ид) значения там еще нет.

есть.
если триггер after, как написал v2v.

Код

create table заказ (id number primary key);
 
Table created
create table выдача (заказ number references заказ(id));
 
Table created
create trigger заказ_ai after insert on Заказ for each row
begin
  insert into выдача values (:new.id);
end;
/
 
Trigger created
insert into заказ values(1);
 
1 row inserted
select * from выдача;
 
     ЗАКАЗ
----------
         1
 

Автор: mgukov 28.12.2009, 01:42
Да, действительно.
Всем спасибо

Автор: Zloxa 28.12.2009, 10:31
меня в этой ситуации больше всего интересует - от чего при проверке констрейнта ошибка не поднимается.
Маcтер таблица ведь находится в состоянии модификации - мутирует.
Шаманство какоето.
 smile 

Автор: DimW 28.12.2009, 11:07
Цитата(Zloxa @  28.12.2009,  10:31 Найти цитируемый пост)
Шаманство какоето.

да вроде ровно все, в случае с before:
Код

SQL> create trigger заказ_bi before insert on Заказ for each row
  2  begin
  3    insert into выдача values (:new.id);
  4  end;
  5  /
 
Trigger created
SQL> insert into заказ values(2);
 
insert into заказ values(2)
 
ORA-02291: integrity constraint (TIS.SYS_C0010351) violated - parent key not found
ORA-06512: at "TIS.ЗАКАЗ_BI", line 2
ORA-04088: error during execution of trigger 'TIS.ЗАКАЗ_BI'
SQL> /


в случае с after, все выполняется в одной транзакции, так что в случае исключения все откатится.

Автор: Zloxa 28.12.2009, 13:45
DimW, то что ровно - то понятно. Не понятно почему в частном случае проверки целостности по FK позволяется доступ к мутирующей таблице, в то время как  в общем случае - нет smile Именно то я и назвал шаманством. Возьмись ты чекануть констрейнт сам - ты бы этого сделать не смог бы.

Автор: DimW 28.12.2009, 14:01
Цитата(Zloxa @  28.12.2009,  13:45 Найти цитируемый пост)
Возьмись ты чекануть констрейнт сам - ты бы этого сделать не смог бы. 

мда, действительно:
Код

SQL> create table заказ (id number);
 
Table created
SQL> create table выдача (заказ number);
 
Table created
SQL> create trigger заказ_ai after insert on Заказ for each row
  2  begin
  3    insert into выдача values (:new.id);
  4  end;
  5  /
 
Trigger created
SQL> create trigger выдача_bi before insert on выдача for each row
  2  declare
  3   n number;
  4  begin
  5    select count(1) into n from заказ where id = :new.заказ;
  6    if n=0 then
  7      raise_application_error(-20555, 'parent key not found');
  8    end if;
  9  end;
 10  /
 
Trigger created
SQL> insert into заказ values(1);
 
insert into заказ values(1)
 
ORA-04091: table TIS.ЗАКАЗ is mutating, trigger/function may not see it
ORA-06512: at "TIS.ВЫДАЧА_BI", line 4
ORA-04088: error during execution of trigger 'TIS.ВЫДАЧА_BI'


действительно, настораживает... 
даже не занаю как к этому относиться, как фиче, или багу...  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)