1

考虑一个具有 3 列的表:ID(唯一,取自 Oracle 序列)、CATEGORY 和 CODE(对最后两列没有限制)。

每个类别都有多个附加代码,但代码在该类别中必须是唯一的。例子:

ID    CATEGORY   CODE
1     1          X
2     1          Y
3     1          Y     //wrong

第三个不行,因为我们已经有了类别 1 的代码 Y。

现在考虑一个在插入之前运行的触发器,并检查要插入的值是否正常。也就是说,对于正在插入的记录,触发器读取类别,然后从表中读取具有该类别的所有代码,如果必须插入的记录中的代码已经存在,则引发异常,以便记录未插入。

我的问题是,如果事务隔离级别是READ_COMMITED并且几乎完全相同的时间在两个不同的事务中执行了两个插入但事务稍后提交,那么触发器将在表中“看到”什么?

例子:

(1) 最初,表格如下所示:

ID    CATEGORY   CODE
1     1          X

(2) 有两个事务 T1 和 T2(READ_COMMITED两者的隔离级别);

(3) 两个事务都想插入category = 1 和code = Y;

(4) T1 执行插入,执行触发器。表中没有Y所以可以插入;

(5) T2执行插入,触发执行。表中没有Y(T1还没有提交)所以可以插入;

(6) T1 提交,表格现在看起来像这样:

ID    CATEGORY   CODE
1     1          X
2     1          Y

(7) T2 现在提交。这里会发生什么?我得到一个错误并且没有插入记录还是得到下表:

ID    CATEGORY   CODE
1     1          X
2     1          Y
3     1          Y     //this is wrong

?!

触发器“看到”了什么以及插入会发生什么?

4

1 回答 1

7

不要使用触发器进行此类验证。触发器不会扩展。此外,正如您所注意到的,它们不适用于多用户环境。这就是为什么大自然给了我们独特的限制。

alter table your_table
    add constraint yr_tab_uk unique (category, code)
    using index
/
于 2009-08-31T09:31:58.733 回答