七叶笔记 » 数据库 » PostgreSQL中enable、disable和validate外键约束的实例

PostgreSQL中enable、disable和validate外键约束的实例

假设我们想通过脚本向表中加载一些数据。因为我们不知道脚本中加载的顺序,我们决定将表t2上的外键约束禁用掉,在数据加载之后载开启外键约束:

这里看起来可能有点奇怪,但是它的确禁用了外键约束。如果有其他外键约束,当然也是被禁用了。

我们再来看看表t2:

关键字all将表上的其他内部触发器也禁用了,需要superser才可以执行成功。

那作为普通用户,该如何禁用触发器呢?

具体语法为:

回到t1、t2表。

这里插入了一条在t1中不匹配的记录,但是插入成功了。

是不是很惊讶,PostgreSQL没有报告不匹配的记录。为什么呢?

查看一个pg_constraint:

convalidated字段的值为t,表明该外键约束还是有效的。

哪怕是我们再次将其disable,仍然会显示是有效的:

这表明当我们开启(enable)内部触发器的时候,PostgreSQL不会验证(validate)约束,因此也不会验证数据是否会有冲突,因为外键约束的状态始终是有效的。

我们需要做的是先将其变成无效的:

现在,可以看到状态是无效的了:

继续插入数据:

是不是更惊讶了?创建了一个无效的约束,只是通知PostgreSQL

不要扫描整个表去验证所有的行记录是否有效。对于新插入或更新的行,仍然会检查是否满足约束条件,这就是为什么上面插入失败了。

我们该怎么做呢?

1.删除所有的外键

2.加载数据

3.重新创建外键,但是将其状态设置成无效的,从而避免扫描整个表。之后,新的数据会被验证了

4.在系统负载低的时候开启约束验证(validate the constraints)

另一种方法是:

这样做不好的方面是,在下一次提交时才起作用,因此,你需要将所有的工作放到一个事务中。

本文的关键点是,下面的假设将验证你的数据是错误的:

这只会验证新的数据,但是并不保证所有的数据都满足约束:

最终,还有一种方式来解决,直接修改pg_constraint目录表。但是并建议用户这么做!

以上为个人经验,希望能给大家一个参考,也希望大家多多支持七叶笔记。如有错误或未考虑完全的地方,望不吝赐教。

相关文章