SQLite3“忘记”使用外键。

19

我正在使用Ruby和SQLite3,但我的外键在Sqlite3中的尝试不幸没有成功。根据sqlite3 --version,安装了版本3.7.13。据我所知,自版本3.6.x以来,Sqlite3支持外键。

我知道默认情况下外键是被禁用的,需要使用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)

很不幸,我可以愉快地插入以未知 app-ids 为标识的行到 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_ids的行。


2
我想我可以通过评论回答自己的问题(而不是回答,因为声望太低):文档说:外键约束默认情况下被禁用(出于向后兼容性考虑),因此必须为每个数据库连接单独启用。这很烦人,但现在终于可以工作了。 - cara
1
相关问题:如果添加了违反外键约束的数据,并随后将foreign_keys标志设置为on,是否会导致错误? - W7GVR
3个回答

34

我认为我可以回答自己的问题:文档中写到:外键约束默认被禁用(为了向后兼容),所以必须为每个数据库连接单独启用。虽然有些烦人,但现在终于可以工作了。


PRAGMAs 永远不会被保存。除了那些明确目的是设置文件元数据的 PRAGMA 之外,它们总是只对当前连接产生影响。 - Bachsau

17

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

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

15
~/.sqliterc 中插入以下行是永久默认开启 foreign_keys 的一种方法。
PRAGMA foreign_keys = ON;

请注意,这将影响所有您的数据库...


1
@MuhammadAdeel 这个问题在于它只为您的用户启用了外键。如果其他人可能使用您的应用程序,并且如果检查外键很重要,最好在建立连接的地方强制执行它。 - ajwood
我尝试在我的Flask应用程序中使用这个,但它没有起作用。(是的,我已经重新启动了它等等。) - code_dredd
这仅影响交互式客户端,因此对开发没有用处。 - Bachsau
这个文件在Ubuntu 18.04中似乎不存在。 - Lost Crotchet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接