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

有没有办法强制进行SQLite约束检查?,sqlite,foreign-keys,referential-integrity,Sqlite,Foreign Keys,Referential Integrity,例如,假设DB的外键A.b_id->b.id在删除时设置为NULL。 如果删除了具有某些B.id的记录,则所有B_id引用都将设置为NULL 但是,如果一个已经包含A.b_id的值不在b.id中的记录(它是在不支持外键的情况下插入的),有没有办法强制SQLite DB检查外键并将此类数据设置为NULL 事实上,首先我要解决一个DB升级任务 启动时应用程序检查内部数据库(资源)的版本是否高于用户数据库。 如果是这样,它备份用户数据库,将内部空数据库复制到用户存储。然后关闭外键支持并用备份中的数据填

例如,假设DB的外键A.b_id->b.id在删除时设置为NULL。 如果删除了具有某些B.id的记录,则所有B_id引用都将设置为NULL

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

事实上,首先我要解决一个DB升级任务

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

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

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


提前谢谢你的帮助

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

或对于单表检查:

PRAGMA schema.foreign_key_check(table-name); 
从文档中:

foreign_key_check pragma检查数据库或名为 “表名”,用于违反的外键约束。这个 外键检查pragma为每个外键返回一行输出 违反每个结果行中有四列。第一列 包含REFERENCES子句的表的名称。这个 第二列是包含无效行的行ID REFERENCES子句,如果子表是不带ROWID的表,则为NULL 桌子第三列是引用的表的名称。 第四列是特定外键约束的索引 那失败了。外键检查输出的第四列 pragma是与输出中的第一列相同的整数 外键列表pragma。如果指定了“表名”,则 选中的外键约束是由引用创建的约束 CREATETABLE语句中用于表名的子句

检查使用此
PRAGMA
语句或其对应函数
PRAGMA\u foreign\u key\u Check()
的简化方法

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

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

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

启用外键支持不会对现有数据执行任何引用完整性检查。是的,我知道。所以,正如你所看到的,我很感兴趣的是有一个命令来强制进行这样的检查。很好,谢谢。根据国外经验,sqlite 3.7.16中增加了密钥检查。我已经用SQLite 3.24.0检查过了,它可以正常工作。除了答案之外,pragma_foreign_key_list(table)通常还可以用于从失败的特定外键约束(pragma_foreign_key_check return的第四列)的索引中获取孤立字段名(本例中为b_id)@Oleg yes,尽管在3.27.0中函数pragma_foreign_key_check()将表名作为参数不起作用,但如果没有它和WHERE子句,则可以起作用。
UPDATE A
SET b_id = NULL
WHERE rowid IN (SELECT rowid FROM pragma_foreign_key_check('A'))