【发布时间】:2015-11-07 22:38:20
【问题描述】:
在 Oracle (11.2.0.1) 中,我有 2 个表,假设 A 和 B 之间存在引用约束(“删除级联”)。 A 是 B 的“父级”。
create table A (id number(9) not null primary key);
create table B (id number(9) not null primary key, parent_id not null references A(id) on delete cascade);
子表在删除时也有一个相关的复合触发器(主要目的是避免在一系列复杂的完整性检查中出现突变错误)。
create or replace trigger trg_b
for delete on b
compound trigger
type b_table is table of b%rowtype;
b_collection b_table := b_table();
before each row is
begin
b_collection.extend;
b_collection(b_collection.last).id := :old.id;
b_collection(b_collection.last).parent_id := :old.parent_id;
end before each row;
after statement is
begin
for i in b_collection.first .. b_collection.last loop
--logging into another table in an autonomous transaction
end loop;
b_collection.delete;
end after statement;
end trg_b;
使用这些表的算法之一如下:
- 所有具有特定 parent_id 的行都将从 B 中删除。
- 额外检查是否没有剩余子行。
- 从父 A 中删除此特定 ID。
在我们的生产环境中,第 3 步在字符串 b_collection.first .. b_collection.last 处生成异常 ORA-06502: PL/SQL: numeric or value error。这意味着从父表中删除会导致触发子表上的触发器,即使没有可能的子行受到影响。这可能是有道理的,因为触发触发器时集合不存在并且第一个和最后一个集合索引为 NULL,但我无法重现这种行为。
在我们的开发环境中,当我尝试从 B 中删除一些不存在的 id/parent_id 时,我只会得到一个 ORA-06502。当我尝试从 A 中删除一些存在的(没有子行)或不存在的 id 时,我没有收到任何错误 - 0 行被删除,0 个子行受到影响。从记录中我可以告诉孩子相关的触发器在这种情况下甚至没有被触发。为什么不呢?
任何想法为什么所描述的行为可能如此不同?我错过了什么?
【问题讨论】:
标签: oracle plsql oracle11g triggers