#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 отлично работают в триггерах.