有没有办法强制 SQLite 约束检查?

问题描述

例如,假设 DB 有外键 A.b_id -> B.id,删除时带有 SET NULL。 如果某个 B.id 的记录被删除,所有 b_id 引用将被设置为 NULL。

但是如果 A 已经包含 A.b_id 具有不在 B.id 中的值的记录(它是在没有外键支持的情况下插入的),有没有办法强制 SQLite DB 检查外键并将此类数据设置为 NULL?

事实上,首先我正在解决数据库升级任务。

在启动应用程序时检查内部数据库(资源)的版本是否高于用户数据库。 如果是这样,它备份用户数据库,将内部空数据库复制到用户存储。然后关闭外键支持并用备份中的数据填充新数据库,自动为所有具有相同名称的列逐表插入循环表。重新开启外键支持。

一切正常,但如果旧数据库的某个表中没有外键约束,而新数据库有外键约束,则数据将按原样插入并且链接无法指向任何地方(可能错误链接是不可避免的并且不相关提问)。

是的,我了解一种在不关闭外键支持的情况下插入的方法,但它需要了解我想避免的表依赖顺序。

提前感谢您的帮助!

解决方法

虽然我不知道有什么方法可以自动将表中一列的所有孤立值设置为 NULL(应该)引用另一个表中的另一列,但有一种方法可以获取报告所有这些情况,然后采取相应的行动。
这是 PRAGMA 语句 foreign_key_check

PRAGMA schema.foreign_key_check;

或单表检查:

PRAGMA schema.foreign_key_check(table-name); 

来自文档:

foreign_key_check pragma 检查数据库,或调用的表 “表名”,用于违反的外键约束。这 foreign_key_check pragma 为每个外键返回一行输出 违反。每个结果行中有四列。第一列 是包含 REFERENCES 子句的表的名称。这 第二列是包含无效行的 rowid REFERENCES 子句,如果子表是 WITHOUT ROWID,则为 NULL 桌子。第三列是所引用的表的名称。 第四列是具体外键约束的索引 那失败了。 foreign_key_check 输出中的第四列 pragma 是与输出中的第一列相同的整数 foreign_key_list 编译指示。当指定了“表名”时,唯一的 检查的外键约束是那些由 REFERENCES 创建的 表名的 CREATE TABLE 语句中的子句。

检查使用此 PRAGMA 语句或其对应函数 pragma_foreign_key_check() 的方法的简化 demo

您可以获得每个表中所有有问题的行的 rowid 列表。

在您的情况下,您可以执行一个 UPDATE 语句,该语句将设置为 NULL 所有孤立的 b_id

UPDATE A
SET b_id = NULL
WHERE rowid IN (SELECT rowid FROM pragma_foreign_key_check() WHERE "table" = 'A')

这也适用于更高版本的 SQLite:

UPDATE A
SET b_id = NULL
WHERE rowid IN (SELECT rowid FROM pragma_foreign_key_check('A'))

但它似乎不适用于 SQLite 3.27.0

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...