【问题标题】:SQLite3 "forgets" to use foreign keysSQLite3“忘记”使用外键
【发布时间】: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:这会导致错误吗?

标签: sql ruby sqlite raspbian


【解决方案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 中似乎不存在
    猜你喜欢
    • 2016-12-15
    • 1970-01-01
    • 2013-02-09
    • 1970-01-01
    • 2017-02-13
    • 2011-09-06
    • 2020-02-29
    • 2012-11-12
    相关资源
    最近更新 更多