验证约束有时会验证,有时不会

时间:2018-08-14 20:56:06

标签: postgresql

我有一个名为base_types的表,其中包含此约束:

ALTER TABLE public.base_types
    ADD CONSTRAINT base_type_gas_type_fk FOREIGN KEY (gas_type)
    REFERENCES public.gas_types (gas_type) MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE NO ACTION
    DEFERRABLE INITIALLY DEFERRED;

我有一个名为alarm_history的表,其中包含五个约束,包括这个约束:

ALTER TABLE public.alarm_history
    ADD CONSTRAINT alarm_history_device_fk FOREIGN KEY (device)
    REFERENCES public.bases (alarm_device) MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE NO ACTION
    DEFERRABLE INITIALLY DEFERRED;

我正在尝试将一个数据库从一个不会困扰任何奇怪而无用的约束的数据库转换为一个使用它们的数据库。我从这个脚本开始:

delete from gas_types;
select conversion.convert_base_types();
alter table base_types validate constraint base_type_gas_type_fk;


select conversion.convert_alarm_history();
alter table alarm_history validate constraint alarm_history_base_fk;
alter table alarm_history validate constraint alarm_history_charge_fk;
alter table alarm_history validate constraint alarm_history_cooler_fk;
alter table alarm_history validate constraint alarm_history_device_fk;
alter table alarm_history validate constraint alarm_history_furnace_fk;

我正确地收到一条错误消息,告诉我新的base_types记录中的gas_type字段与gas_types表中的任何内容都不匹配,因为gas_types表为空。但是,如果我注释掉base_types命令,我会在alarm_history表中获得18,000条漂亮,闪亮的新记录,尽管事实上每个记录都违反了该表的五个外键约束中的至少一个,因为所有表都包含这些键指的是空的。我需要确保转换后的数据是一致的,因此需要验证约束,但这显然没有发生。为什么不呢?

1 个答案:

答案 0 :(得分:0)

由于上面的约束创建为DEFERRABLE INITIALLY DEFERRED,因此直到提交DML语句(您的delete语句),或者直到您显式验证约束为止,才对它们进行检查。

这是最初延迟的可延迟约束的正常和预期操作。

要在当前交易中更改此功能,可以发出SET CONSTRAINTS命令来更改此功能:

SET CONSTRAINTS alarm_history_device_fk IMMEDIATE;
delete from gas_types;

哪些应该引起外键冲突,从而提前提醒您您的数据取决于要删除的记录。