首页 > 解决方案 > 有没有办法强制 SQLite 约束检查?

问题描述

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

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

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

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

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

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

提前感谢您的帮助!

标签: sqliteforeign-keysreferential-integrity

解决方案


尽管我不知道有一种方法可以自动设置NULL表中(应该)引用另一个表中的另一列的列的所有孤立值,但是有一种方法可以获取所有这些情况的报告,然后采取相应的行动.
这是PRAGMA声明foreign_key_check

PRAGMA schema.foreign_key_check;

或单表检查:

PRAGMA schema.foreign_key_check(table-name); 

从文档中:

foreign_key_check pragma 检查数据库或名为“table-name”的表是否违反了外键约束。foreign_key_check 杂注为每个外键违规返回一行输出。每个结果行中有四列。第一列是包含 REFERENCES 子句的表的名称。第二列是包含无效 REFERENCES 子句的行的 rowid,如果子表是 WITHOUT ROWID 表,则为 NULL。第三列是引用的表的名称。第四列是失败的特定外键约束的索引。foreign_key_check pragma 输出中的第四列与 foreign_key_list pragma 输出中的第一列是相同的整数。指定“表名”时,

检查使用此语句或其功能对应物的方式的简化演示PRAGMApragma_foreign_key_check()

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

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

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


推荐阅读