Триггер Oracle перед вставкой

#sql #oracle #triggers

Вопрос:

вот мой пример триггера

 create or replace TRIGGER INVOICES_INSERT
BEFORE INSERT ON INVOICES 
FOR EACH ROW
BEGIN
    if :new.INVOICE_TYPE = 'Purchase'
    
    insert into Purchases (ID, Name, Type) Values (:new.ID, :new.Name, :new.Type)
END;
 

В моем примере триггера я получаю записи как в таблицах Счетов, так и в таблицах покупок. Но если условие выполнено в инструкции IF, я хочу записывать данные только в таблицу покупок.

Возможно ли это сделать в триггере.

Комментарии:

1. Правильно ли я понимаю: вы хотите перехватить все вставки «Покупка» счета-фактуры и написать строку покупки вместо строки счета-фактуры? В то время как человек или процесс думают, что они вставляют в счет-фактуру, вы хотите вставлять строки, не связанные с покупкой, в счета-фактуры и добавлять строки в покупки без того, чтобы процесс или человек знали, что это происходит? Они должны думать, что они вставлены в счета-фактуры, в то время как это не всегда так?

2. Если мое предположение верно, то почему вы вообще хотите это сделать? Почему кто-то думает, что он вставляет данные в одну таблицу, в то время как данные передаются в другую? Вы можете выбрать все покупки и все не покупки из таблицы счетов-фактур, просто применив условие «где». И вы даже можете создавать представления, в которых для удобства отображаются те или иные данные. Так зачем же этот хитрый план?

Ответ №1:

Ты не можешь делать то, что хотел, не таким способом. Почему? Потому что триггер срабатывает перед вставкой invoices , что означает, что строка будет вставлена в invoices таблицу независимо от того, что вы вставили в этот триггер. Да, вы также можете — при желании — вставить строку в purchase таблицу, но вы не можете избежать вставки в invoices нее .

Говоря, что вы не можете сделать это таким образом, я хотел сказать, что, в конце концов, есть другой способ сделать это. Как? Использование представления и триггера вместо. Вот пример.

Примеры таблиц:

 SQL> create table invoices
  2   (id       number,
  3    name     varchar2(10),
  4    type     varchar2(10));

Table created.

SQL> create table purchase
  2   (id       number,
  3    name     varchar2(10),
  4    type     varchar2(10));

Table created.
 

Вид, простое объединение:

 SQL> create or replace view v_invpur as
  2    select id, name, type from invoices
  3    union all
  4    select id, name, type from purchase;

View created.
 

Вместо триггера: в зависимости от типа он вставляет строку в соответствующую таблицу:

 SQL> create or replace trigger trg_ioi_vinvpur
  2    instead of insert on v_invpur
  3    for each row
  4  begin
  5    if :new.type = 'invoice' then
  6       insert into invoices (id, name, type)
  7         values (:new.id, :new.name, :new.type);
  8    elsif :new.type = 'purchase' then
  9       insert into purchase (id, name, type)
 10         values (:new.id, :new.name, :new.type);
 11    end if;
 12  end;
 13  /

Trigger created.
 

Тестирование:

 SQL> insert into v_invpur (id, name, type)
  2    values (1, 'Little', 'purchase');

1 row created.

SQL> select * from invoices;

no rows selected

SQL> select * from purchase;

        ID NAME       TYPE
---------- ---------- ----------
         1 Little     purchase

SQL>
 

Видишь? В invoices таблице ничего нет, но в purchase таблицу вставлена строка.

Комментарии:

1. спасибо за ваш скрипт, но он не работает, потому что в таблице счетов-фактур около 30 столбцов, а в таблице покупок примерно на 15 меньше. У меня есть проблема в профсоюзе.

2. Это не должно быть проблемой. ОБЪЕДИНЕНИЕ требует, чтобы операторы SELECT имели одинаковое количество столбцов и чтобы их типы данных совпадали. Поэтому вместо этих «отсутствующих» столбцов ПРИВЕДИТЕ значение NULL к соответствующему типу данных. Например, cast (NULL as number) col1, cast (NULL as varchar2(10)) col2, ... .

Ответ №2:

Есть много способов сделать это … например . if Но простой способ-это:

 insert into Purchases (ID, Name, Type) 
    select :new.ID, :new.Name, :new.Type
    from dual
    where :new.INVOICE_TYPE = 'Purchase';
 

То есть «условная» логика может быть просто частью insert .

Комментарии:

1. в этом примере данные вставляются только в таблицу покупок?

2. @Felichino . . . Это вставляет в Purchases таблицу только покупки.

3. да, ваш код будет работать на простом скрипте или внутри хранимой процедуры, но в триггере он не работает

4. @Felichino . . . Я не уверен, почему ты так говоришь. INSERT s отлично работают в триггерах.