【问题标题】:Is there any way to force SQLite constrains checks?有没有办法强制 SQLite 约束检查?
【发布时间】:2021-07-02 07:46:45
【问题描述】:

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

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

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

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

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

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

提前感谢您的帮助!

【问题讨论】:

  • 开启外键支持不会对现有数据强制执行任何参照完整性检查。
  • 是的,我知道。所以,正如你所看到的,我很感兴趣是否有一个命令可以强制进行此类检查。

标签: sqlite foreign-keys referential-integrity


【解决方案1】:

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

PRAGMA schema.foreign_key_check;

或单个表检查:

PRAGMA schema.foreign_key_check(table-name); 

来自文档:

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

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

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

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

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.org/releaselog/3_7_16.htmlforeign_key_check 在 sqlite 3.7.16 中添加。我已经检查过 SQLite 3.24.0 它可以工作。除了 answer 之外,pragma_foreign_key_list(table) 一般可用于从失败的特定外键约束的索引(pragma_foreign_key_check 返回的第四列)中获取孤立的字段名称(在我们的示例中为 b_id)
  • @Oleg 是的,虽然在 3.27.0 中,以表名作为参数的函数 pragma_foreign_key_check() 不起作用,但没有它和 WHERE 子句也可以工作。
猜你喜欢
  • 1970-01-01
  • 2013-01-23
  • 1970-01-01
  • 2012-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-17
  • 2012-09-29
相关资源
最近更新 更多