Oracle:何时检查约束?

问题描述 投票:1回答:3

据我所知,通常应在交易结束时检查约束。

因此,在一个简单的示例中,我们有一个具有唯一列A的表P,这是它的主键,还有一个具有主键B和外键P的表FA.P上,以下内容应该起作用(在空表上):

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中声明(遵循A C ID属性)

[t]该事务将数据库从一个一致状态转移到另一一致状态。

因此,可以期望介于两者之间的状态不必一定保持一致。这当然适用于Oracle提供的示例:钱从一个帐户转移到另一个帐户,而在这两者之间,总金额不匹配(不一致),因为从一个帐户中取出了钱,但不尚未添加到另一个。那么为什么外键约束看起来不一样?

sql oracle transactions constraints
3个回答
1
投票

如果是,是否有任何方法可以强制执行此行为

是,是的。这称为延迟约束。

如果延迟约束,则在事务结束时检查约束,而不是在执行语句时检查约束。

alter table some_table
   add constraint fk_something 
   foreign key (some_column) references other_table(pk_column)
   deferrable initially deferred;

关于this answerinitially deferred之间的区别的说明,请参见initially immediate


0
投票

解决此问题的一种方法是defer块内的相关约束,例如:

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;

0
投票

除非您将约束明确定义为deferred constraint,否则将在将行插入表中时检查约束。

在提交事务之前,实际上在外部看不到数据,但是逐步检查了数据完整性。

© www.soinside.com 2019 - 2024. All rights reserved.