SQLite 外键

Posted

技术标签:

【中文标题】SQLite 外键【英文标题】:SQLite Foreign Key 【发布时间】:2012-07-17 17:07:52 【问题描述】:

我正在遵循http://www.sqlite.org/foreignkeys.html 上的 SQLite 文档中的说明,但是我尝试添加外键失败了。这是我的创建语句:

CREATE TABLE 
    checklist (
        _id INTEGER PRIMARY KEY AUTOINCREMENT, 
        checklist_title TEXT,
        description TEXT,
        created_on INTEGER, 
        modified_on INTEGER
    );

CREATE TABLE 
    item (
        _id INTEGER PRIMARY KEY AUTOINCREMENT,  
        FOREIGN KEY(checklist_id) REFERENCES checklist(_id), 
        item_text TEXT, item_hint TEXT, 
        item_order INTEGER, 
        created_on INTEGER, 
        modified_on INTEGER
    );

第一张桌子做得很好。错误发生在第二个语句中。我已经尝试过将两个查询包装在一个事务中,而没有。这是错误:

外键定义(代码 1)中的未知列“checklist_id”:,编译时:CREATE TABLE item (_id INTEGER PRIMARY KEY AUTOINCREMENT, FOREIGN KEY(checklist_id) REFERENCES checklist(_id), item_text TEXT, item_hint TEXT, item_order INTEGER , created_on INTEGER, modified_on INTEGER)

【问题讨论】:

【参考方案1】:

在将其添加为外键之前,您仍然需要创建列 checklist_id INTEGER

原来是这样:

CREATE TABLE 
    checklist (
        _id INTEGER PRIMARY KEY AUTOINCREMENT, 
        checklist_title TEXT,
        description TEXT,
        created_on INTEGER, 
        modified_on INTEGER
    );

CREATE TABLE 
    item (
        _id INTEGER PRIMARY KEY AUTOINCREMENT,  
        checklist_id INTEGER,
        item_text TEXT, 
        item_hint TEXT, 
        item_order INTEGER, 
        created_on INTEGER, 
        modified_on INTEGER,
        FOREIGN KEY(checklist_id) REFERENCES checklist(_id)
    );

【讨论】:

【参考方案2】:

我认为上述答案并不完全正确,或者至少有点误导。 正如他们正确指出的那样,您可以创建列,然后在单独的行上添加外键约束。这称为指定表约束。

但也有更短的语法,当仅应用于 1 列时,也可以指定所有 4 个可能的约束(PRIMARY KEYUNIQUECHECKFOREIGN KEY)内联(例如NOT NULL),作为列约束。 IE。你可以写:

CREATE TABLE 
item (
    _id INTEGER PRIMARY KEY AUTOINCREMENT,  
    checklist_id REFERENCES checklist(_id), 
    item_text TEXT, item_hint TEXT, 
    item_order INTEGER, 
    created_on INTEGER, 
    modified_on INTEGER
);

顺便说一句,如果您不确定正确的语法,official documentation 有非常漂亮的铁路图。

【讨论】:

为什么有人想要外键的唯一约束?通常在 1:N 关系中,您将外键列放入 N 实体的表中以引用父 1 实体。因此,N 表中将有许多行将引用相同的 1 行。 UNIQUE 约束不会阻止这种情况吗?我是不是误会了什么? sqlite.org/foreignkeys.html#fk_indexes 的最后一个示例显示了 REFERENCES 简写,它没有指定父列只是父表(我猜系统会扣除该列作为父表的主键)。但是它确实需要一个明确的索引创建语句。 对不起,我不是说你应该或者可以结合UNIQUEREFERENCES。您只能选择其中之一,不能同时选择两者。至于你的第二个问题,是的,除非'子表引用父级的主键而没有指定主键列并且父级中的主键列数与子键列数不匹配,否则会扣除列。 '。【参考方案3】:

将 FOREIGN KEY 定义放在 SQL 语句的末尾

【讨论】:

【参考方案4】:

只是您的 item 表中缺少checklist_id 列。您需要先声明它,然后再将其设置为FOREIGN KEY。您尝试在不存在的列上创建 FK,这就是它不起作用的原因。

所以你需要添加这个:

checklist_id INTEGER,
FOREIGN KEY(checklist_id) REFERENCES checklist(_id)

现在应该可以了。

【讨论】:

【参考方案5】:

您需要在使用 FOREIGN KEY() 包装之前包含列名。

CREATE TABLE 
    item (
        _id INTEGER PRIMARY KEY AUTOINCREMENT,  
        checklist_id INTEGER,
        FOREIGN KEY(checklist_id) REFERENCES checklist(_id), 
        item_text TEXT, item_hint TEXT, 
        item_order INTEGER, 
        created_on INTEGER, 
        modified_on INTEGER
    );

【讨论】:

以上是关于SQLite 外键的主要内容,如果未能解决你的问题,请参考以下文章

SQLite3“忘记”使用外键

SQLite 外键

世博sqlite外键

在没有命令的情况下启用 SQLite 外键

播放框架 - SQLite:启用外键

在 SQLite 中启用外键约束