Oracle:什么时候检查约束?
Oracle: When are constraints checked?
根据我的理解,通常应在事务结束时检查约束。
因此,在一个简单的示例中,我们有一个 table A
,其中唯一的列 P
是其主键,而 table B
与主键 P
和外键 F
在 A.P
上,以下应该有效(在空 tables 上):
begin
insert into B (P, F)
values (1, 1);
insert into A (P)
values (1);
commit;
end;
但是,Oracle 给我错误(德语):
[23000][2291] ORA-02291: Integritäts-Constraint (DATABASE.AB_constraint) verletzt - übergeordneter Schlüssel nicht gefunden
ORA-06512: in Zeile 3
Position: 0
转换为违反完整性约束 - 未找到引用的密钥。如果我颠倒顺序
begin
insert into A (P)
values (1);
insert into B (P, F)
values (1, 1);
commit;
end;
它工作正常。 Oracle 中事务结束时是否未验证约束?如果是这样,是否有任何方法可以强制执行此行为?
在 Oracle docs 中指出(在 ACID 属性之后)
[t]he transaction takes the database from one consistent state to another consistent state.
因此可以预期两者之间的状态不一定必须一致。这当然适用于 Oracle 提供的示例:资金从一个账户转移到另一个账户,而在两者之间,资金总额不匹配(不一致),因为资金从一个账户中移除,但不是还添加到另一个。那为什么外键约束好像不一样呢?
除非您将约束明确定义为 deferred constraint,否则会在将行插入 table 时检查约束。
在提交事务之前,数据在外部实际上是不可见的,但会逐步检查数据完整性。
And if so, is there any way of enforcing this behaviour
是的,就是这样。它被称为延迟约束。
如果延迟约束,则在事务结束时检查它,而不是在执行语句时检查。
alter table some_table
add constraint fk_something
foreign key (some_column) references other_table(pk_column)
deferrable initially deferred;
有关 initially deferred
和 initially immediate
之间区别的解释,请参阅 this answer
解决此问题的一种方法是 延迟 块内的相关约束,例如:
begin
execute immediate 'set constraint ab_constraint deferred';
insert into B (P, F) values (1, 1);
insert into A (P) values (1);
execute immediate 'set constraint ab_constraint immediate';
commit;
end;
根据我的理解,通常应在事务结束时检查约束。
因此,在一个简单的示例中,我们有一个 table A
,其中唯一的列 P
是其主键,而 table B
与主键 P
和外键 F
在 A.P
上,以下应该有效(在空 tables 上):
begin
insert into B (P, F)
values (1, 1);
insert into A (P)
values (1);
commit;
end;
但是,Oracle 给我错误(德语):
[23000][2291] ORA-02291: Integritäts-Constraint (DATABASE.AB_constraint) verletzt - übergeordneter Schlüssel nicht gefunden
ORA-06512: in Zeile 3
Position: 0
转换为违反完整性约束 - 未找到引用的密钥。如果我颠倒顺序
begin
insert into A (P)
values (1);
insert into B (P, F)
values (1, 1);
commit;
end;
它工作正常。 Oracle 中事务结束时是否未验证约束?如果是这样,是否有任何方法可以强制执行此行为?
在 Oracle docs 中指出(在 ACID 属性之后)
[t]he transaction takes the database from one consistent state to another consistent state.
因此可以预期两者之间的状态不一定必须一致。这当然适用于 Oracle 提供的示例:资金从一个账户转移到另一个账户,而在两者之间,资金总额不匹配(不一致),因为资金从一个账户中移除,但不是还添加到另一个。那为什么外键约束好像不一样呢?
除非您将约束明确定义为 deferred constraint,否则会在将行插入 table 时检查约束。
在提交事务之前,数据在外部实际上是不可见的,但会逐步检查数据完整性。
And if so, is there any way of enforcing this behaviour
是的,就是这样。它被称为延迟约束。
如果延迟约束,则在事务结束时检查它,而不是在执行语句时检查。
alter table some_table
add constraint fk_something
foreign key (some_column) references other_table(pk_column)
deferrable initially deferred;
有关 initially deferred
和 initially immediate
解决此问题的一种方法是 延迟 块内的相关约束,例如:
begin
execute immediate 'set constraint ab_constraint deferred';
insert into B (P, F) values (1, 1);
insert into A (P) values (1);
execute immediate 'set constraint ab_constraint immediate';
commit;
end;