请考虑以下代码:
drop table if exists demo cascade;
drop table if exists child cascade;
create table demo
(
id bigint not null
constraint demo_pk primary key
);
create table child
(
id bigint not null
constraint child_pk primary key,
pid bigint,
constraint child_pid_fk
foreign key (pid)
references demo (id)
deferrable initially deferred -- remove this line and exceptions get caught
);
insert into demo values (1);
insert into child values (11, 1);
do language plpgsql $$
begin
delete from demo where id = 1;
exception
when others then
raise notice 'exception caught';
end;
$$;
我想捕获约束引发的任何异常,但出于性能原因,我推迟检查约束直到commit(deferrable initially deferred
)。有没有办法在不启用immediate
模式的情况下捕获异常?
答案 0 :(得分:4)
可以为您的交易设置IMMEDIATE
的可延迟约束,而无需“立即开启模式”(不更改约束定义)。
这正是这个单独的命令SET CONSTRAINTS
的用途:
SET CONSTRAINTS child_pid_fk IMMEDIATE;
或者如果您不知道约束名称:
SET CONSTRAINTS ALL IMMEDIATE;
SET CONSTRAINTS
设置当前交易中约束检查的行为。
大胆强调我的。
和
当
SET CONSTRAINTS
更改约束的模式时DEFERRED
到IMMEDIATE
,新模式会追溯生效: 任何未经检查的未完成的数据修改 在执行期间检查事务的结尾SET CONSTRAINTS
命令。如果违反任何此类约束,则SET CONSTRAINTS
失败(并且不会更改约束模式)。 因此,SET CONSTRAINTS
可用于强制检查约束 发生在交易中的特定点。
正是你需要的。