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“忘记”使用外键的主要内容,如果未能解决你的问题,请参考以下文章