SQLite3“忘记”使用外键

Posted

技术标签:

【中文标题】SQLite3“忘记”使用外键【英文标题】:SQLite3 "forgets" to use foreign keys 【发布时间】:2013-02-24 10:46:27 【问题描述】:

我在 SQLite3 中使用 Ruby,但很遗憾,我尝试在 Sqlite3 中使用外键没有成功。根据sqlite3 --version,安装的是3.7.13版本。据我所知,Sqlite3 从 3.6.x 版本开始支持外键。

我知道外键默认是停用的,必须使用PRAGMA foreign_keys = ON; 激活。在我的 Ruby db-create-script 中,我正在做这样的事情:

sql = <<-SQL
  PRAGMA foreign_keys = ON;
  CREATE TABLE apps (
    id ....
  );
  CREATE TABLE requests (
    ...
    app_id INTEGER NOT NULL,
    FOREIGN KEY(app_id) REFERENCES apps(id),
  );
  ...
SQL
db.execute_batch(sql)

不幸的是,我可以很高兴地将行插入到具有未知应用程序 ID 的 requests,它可以工作,但当然不应该。

有趣:直接使用 sqlite3 shell,我可以观察到以下行为:

$ sqlite3 database.db
sqlite> PRAGMA foreign_keys = ON;
sqlite> PRAGMA foreign_keys;
1 // as expected
sqlite> .quit
$ sqlite3 database.db
sqlite> PRAGMA foreign_keys;
0 // off ?!

在不退出 sqlite3 shell 的情况下,外键在激活后正在工作(而不是退出 shell)并且我不允许插入具有未知 app_id 的行。

【问题讨论】:

我想我可以回答我自己的问题(在评论中而不是由于低代表的答案):文档说:外键约束默认禁用(为了向后兼容),所以必须分别为每个数据库连接启用。烦人,但它现在终于可以工作了。 相关问题:如果添加了违反外键约束的数据并且随后将foreign_keys标志设置为on:这会导致错误吗? 【参考方案1】:

我想我可以回答我自己的问题:文档说:默认情况下禁用外键约束(为了向后兼容),因此必须为每个数据库连接单独启用。烦人,但它现在终于可以工作了。

【讨论】:

PRAGMA 永远不会被保存。除了有明确目的设置文件元数据的那些之外,它们总是只对当前连接产生影响。【参考方案2】:

将它放在执行 SQL 命令的文件的顶部,它将在运行时启用外键。

db = SQLite3::Database.new("database.db")
db.execute("PRAGMA foreign_keys = ON")

【讨论】:

【参考方案3】:

默认情况下永久打开 foreign_keys 的一种方法是将以下行注入~/.sqliterc

PRAGMA foreign_keys = ON;

请注意,它会影响您的所有数据库...

【讨论】:

@MuhammadAdeel 问题在于它只为您的用户启用外键。如果其他人可能会使用您的应用程序,并且如果检查外键很重要,那么最好在建立连接的地方强制执行它。 我在我的烧瓶应用程序中尝试了这个,但没有成功。 (是的,我确实重新启动了它等等。) 这只影响交互式客户端,因此对开发没有用处。 这个文件在 ubuntu 18.04 中似乎不存在

以上是关于SQLite3“忘记”使用外键的主要内容,如果未能解决你的问题,请参考以下文章

与ORM django和sqlite3数据库相关的问题

sqlite3 sqlite3_preparesqlite3_step使用

SQLite3使用笔记——插入

sqlite3使用简介

IOS 开发学习33 使用sqlite3

SQLite3 of python