Postgresql 为什么';t验证约束是否找到此外键冲突?

Postgresql 为什么';t验证约束是否找到此外键冲突?,postgresql,Postgresql,我想我不明白验证约束应该做什么。我正在转换一个数据库,以便在公司旗舰软件产品即将进行的重大升级中使用。过去的开发人员都很懒惰,他们不需要在应该有外键的地方指定外键。对于我们产品的新版本,将指定并强制执行适当的外键 因此,我想将数据导入到我的新数据库中,然后确保没有外键冲突。在努力解决事务开始和结束的时间以及处理循环键并以惊人的速度一无所获之后,我决定只禁用所有表上的所有触发器(这在PostgreSQL中禁用外键约束检查,因为它们在引擎盖下使用触发器),导入数据,重新启用触发器,然后发出“验证约束

我想我不明白验证约束应该做什么。我正在转换一个数据库,以便在公司旗舰软件产品即将进行的重大升级中使用。过去的开发人员都很懒惰,他们不需要在应该有外键的地方指定外键。对于我们产品的新版本,将指定并强制执行适当的外键

因此,我想将数据导入到我的新数据库中,然后确保没有外键冲突。在努力解决事务开始和结束的时间以及处理循环键并以惊人的速度一无所获之后,我决定只禁用所有表上的所有触发器(这在PostgreSQL中禁用外键约束检查,因为它们在引擎盖下使用触发器),导入数据,重新启用触发器,然后发出“验证约束”命令。然而,在我的小测试脚本中,验证没有发现任何约束冲突。为什么不呢

这是测试脚本。我正在创建一个名为gas\u types\u minimum的表,其中包含一个名为gas\u type的列。我没有在该表中创建任何记录。然后,我创建了一个名为base\u types\u minimum的表,其中包含一个名为base\u type的列和一个名为gas\u type的列。我禁用了它的触发器,这样即使没有gas类型的记录,我也可以插入一个base类型的记录。然后,我插入一个氢基类型,气体类型为“H2”。然后,我再次打开触发器并验证约束。我没有错

DROP TABLE IF EXISTS base_types_minimum;
DROP TABLE IF EXISTS gas_types_minimum;
CREATE TABLE public.gas_types_minimum
(
    gas_type character varying(32) COLLATE pg_catalog."default",
    CONSTRAINT gas_type_minimum_pkey PRIMARY KEY (gas_type)
);

CREATE TABLE public.base_types_minimum
(
    base_type character varying(32) COLLATE pg_catalog."default" NOT NULL,
    gas_type character varying(32) COLLATE pg_catalog."default",
    CONSTRAINT base_type_minimum_pkey PRIMARY KEY (base_type),
    CONSTRAINT base_type_minimum_gas_type_minimum_fk FOREIGN KEY (gas_type)
        REFERENCES public.gas_types_minimum (gas_type) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION
);

alter table base_types_minimum disable trigger all;
insert into base_types_minimum values ('Hydrogen', 'H2');
alter table base_types_minimum enable trigger all;

alter table base_types_minimum validate constraint base_type_minimum_gas_type_minimum_fk;

原因是外键约束已标记为有效,因此未对其进行检查

验证约束
仅对定义为
无效
的约束有用,而您的约束不是。没有支持的方法在以后使约束无效,因为它被认为是无用的

禁用触发器实际上破坏了完整性,无法恢复。这就是为什么如果您是超级用户(他们应该知道他们在做什么),您只能禁用实现外键的触发器

最好的方法是删除已损坏的外键约束

有一个–不受支持!–将约束标记为无效的方式:

UPDATE pg_catalog.pg_constraint
SET convalidated = FALSE
WHERE conname = 'base_type_minimum_gas_type_minimum_fk';

你只能作为超级用户来做,我不推荐这样做。取消外键限制。

非常感谢。由于这种转换非常罕见,而且我有超级用户访问权限,所以我不介意这样做,但我认为这太花哨了。我倾向于在花哨的解决方案上浪费太多的时间。非常感谢你,我一直在努力找出真相!这是一块饼干: