甲骨文数据库。在里面插入带有 Merge 语句的触发器。 Table 正在变异
Oracle DB. Insert Trigger with Merge statament inside. Table is mutating
我有两个后端系统(旧的和新的)共享一个 Oracle 数据库。
在旧系统中,为了保存客户数据,有两个table
customers_A
ID NAME ETC
1 PETE ....
customers_B
ID NAME ETC
1 JOSH ...
2 ROSS ...
在新系统中,我创建了一个名为 All_Costumer 的新 table,以加入那些 table。
这个新 table 分别包含类型 A 和 B 的客户 ID。
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 tables,还有B类客户。
目前,旧系统也可以使用,当创建A类新客户时,数据仅插入customer_A table,但我需要[=54]中的数据=] 也是。
为了解决这个问题,我创建了一个内部有 MERGE INTO 语句的 TRIGGER,如果 table 上不存在,则在 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
有解决办法吗?
我尝试在 DECLARE 部分添加 PRAGMA AUTONOMOUS_TRANSACTION;
,但没有成功。
注意:我无法修改旧系统
眼前的问题是您在针对 table 的触发器中查询 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)
...
您也不能在触发器中提交 - 除非它是自主的,但这是不应该的。你说你试过了,但是如果回滚插入就会中断,因为合并的行仍然存在。因此,希望该提交只是尝试和拒绝该方法的后遗症。
但无论如何它都有效 in this db<>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;
我有两个后端系统(旧的和新的)共享一个 Oracle 数据库。
在旧系统中,为了保存客户数据,有两个table
customers_A
ID NAME ETC
1 PETE ....
customers_B
ID NAME ETC
1 JOSH ...
2 ROSS ...
在新系统中,我创建了一个名为 All_Costumer 的新 table,以加入那些 table。 这个新 table 分别包含类型 A 和 B 的客户 ID。
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 tables,还有B类客户。
目前,旧系统也可以使用,当创建A类新客户时,数据仅插入customer_A table,但我需要[=54]中的数据=] 也是。
为了解决这个问题,我创建了一个内部有 MERGE INTO 语句的 TRIGGER,如果 table 上不存在,则在 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
有解决办法吗?
我尝试在 DECLARE 部分添加 PRAGMA AUTONOMOUS_TRANSACTION;
,但没有成功。
注意:我无法修改旧系统
眼前的问题是您在针对 table 的触发器中查询 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)
...
您也不能在触发器中提交 - 除非它是自主的,但这是不应该的。你说你试过了,但是如果回滚插入就会中断,因为合并的行仍然存在。因此,希望该提交只是尝试和拒绝该方法的后遗症。
但无论如何它都有效 in this db<>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;