Oracle БД. Вставьте триггер с слиянием внутри. Стол мутирует - PullRequest
0 голосов
/ 31 марта 2020

У меня есть две серверные системы (старая и новая), которые совместно используют Oracle DB.

В более старой системе для сохранения данных о клиентах есть две таблицы

Customers_A

ID   NAME  ETC
1    PETE  ....

Customers_B

ID NAME ETC
1  JOSH ...
2  ROSS ...

В новой системе я создал новую таблицу с именем All_Costumer , чтобы присоединиться к этим таблицам. Эта новая таблица содержит идентификаторы клиентов типа A и B. соответственно.

All_Customers

ID           ID_CUSTOMER_A    ID_CUSTOMER_B
A19E----D2B0     1                 null
A19E----D2B1    null                 1
A19E----D2B2    null                 2

Таким образом, когда новая система создает нового клиента типа A, данные вставляются в таблицы customer_A и All_Customers , также с клиентом типа B.

В настоящее время старая система также работает, и когда создается новый клиент типа A, данные вставляется только в таблицу customer_A, но мне нужны эти данные и в All_Customers.

Чтобы решить эту проблему, я создал TRIGGER с инструкцией MERGE INTO внутри, чтобы вставить строку в All_Customers, если ее нет в эта таблица (когда новый клиент типа A создается более старой системой)

CREATE OR REPLACE TRIGGER customers_trg

AFTER INSERT
ON customer_A

FOR EACH ROW

DECLARE
variables that doesn't matters

BEGIN
    MERGE INTO all_customers
        USING (SELECT :new.id id FROM customer_A where id = :new.id) customer
        ON (all_customers.id_customer_a = customer.id)
    WHEN NOT MATCHED THEN
        INSERT (id, id_customer_a)
        VALUES (SYS_GUID(), :new.id, null);
    COMMIT;
END;

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

ORA-04091: table **customer_A** is mutating, trigger/function may not see it

Есть идеи, чтобы решить это? Я попытался добавить PRAGMA AUTONOMOUS_TRANSACTION; в раздел DECLARE, но не сработало.

Примечание: я не могу изменить старую систему

1 Ответ

0 голосов
/ 31 марта 2020

Непосредственная проблема заключается в том, что вы запрашиваете table_a в триггере для этой таблицы; но тебе не нужно. Ваш запрос на слияние

SELECT :new.id id FROM customer_A where id = :new.id

может просто выполнить

SELECT :new.id id FROM dual

, то есть предложение будет иметь вид:

...
        USING (SELECT :new.id id FROM dual) customer
        ON (all_customers.id_customer_a = customer.id)
...

Вы также не можете зафиксировать в триггере - если только автономный, что это не должно быть. Вы сказали, что пытались это сделать, но он ломается, если вставка откатывается, так как объединенная строка все еще будет существовать. Надеюсь, что фиксация - это всего лишь похмелье от попытки и отклонения этого подхода.

Но в любом случае он работает в этой базе данных <> fiddle .

Если вы не Не добавляя GUID, вы можете получить тот же эффект с видом:

create or replace view all_customers (id_customer_a, id_customer_b) as
select id, null from customers_a
union all
select null, id from customers_b;

db <> fiddle

...