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

Is there any way to force SQLite constrains checks?

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

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

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

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

一切正常,但如果旧数据库中的某些table以前没有外键约束,而新数据库有,则数据将按原样插入并且link可以指向无处(可能错误links是不可避免的,与问题无关)。

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

提前感谢您的帮助!

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

PRAGMA schema.foreign_key_check;

或单个 table 检查:

PRAGMA schema.foreign_key_check(table-name); 

来自文档:

The foreign_key_check pragma checks the database, or the table called "table-name", for foreign key constraints that are violated. The foreign_key_check pragma returns one row output for each foreign key violation. There are four columns in each result row. The first column is the name of the table that contains the REFERENCES clause. The second column is the rowid of the row that contains the invalid REFERENCES clause, or NULL if the child table is a WITHOUT ROWID table. The third column is the name of the table that is referred to. The fourth column is the index of the specific foreign key constraint that failed. The fourth column in the output of the foreign_key_check pragma is the same integer as the first column in the output of the foreign_key_list pragma. When a "table-name" is specified, the only foreign key constraints checked are those created by REFERENCES clauses in the CREATE TABLE statement for table-name.

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

您可以获得每个 table 的所有问题行的 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