2

较新版本的 SQLite支持外键约束。可以定义

CREATE TABLE MASTER (_ID INTEGER PRIMARY KEY, ...);
CREATE TABLE SERVANT (_ID INTEGER PRIMARY KEY, MASTERID INTEGER, 
  FOREIGN KEY(MASTERID) REFERENCES MASTER(_ID);

根据文档,默认情况下“NO ACTION”用于 ON DELETE 和 ON UPDATE。但与其他 DBS 不同,“NO ACTION”似乎并不意味着不执行删除或更新。至少根据我的测试(*)并且如果我正确理解文档,这似乎意味着没有采取任何措施来保持完整性:

配置“NO ACTION”意味着:当父键被修改或从数据库中删除时,不采取任何特殊操作。

因此

INSERT INTO MASTER (_ID) VALUES (1);
INSERT INTO SERVANT (_ID, MASTERID) VALUES (1,1);
DELETE FROM MASTER;

给了我一个空的 MASTER 表和一个 SERVANT 表,外键指向无处。

任何人都可以确认这种行为并解释为什么它是这样实现的吗?还是我必须配置一些东西才能使外键支持工作?我是 SQLite 开发的新手,所以如果这是一个愚蠢的问题,请原谅我。

编辑:(*)我的测试有缺陷,请参阅下面的答案

4

2 回答 2

2

我将尝试自己给出一个答案:

不,如果配置正确,SQLite 在这种情况下会保持数据完整性。默认情况下使用“NO ACTION”,如果引用表中仍有引用键(使用 3.7.x 测试),则禁止删除或更新主键。我的错是我不知道PRAGMA foreign_keys = ON;必须为每个与数据库的新连接进行配置。

编辑:我认为 SQLite 文档在这里具有误导性

于 2013-07-11T19:11:49.097 回答
0

你是对的。“NO ACTION”意味着没有做任何事情来保持外键约束的完整性。有关可以设置的选项的详细信息,请参阅文档。

在这种情况下,您可以设置 4 个其他选项。RESTRICT、SET NULL、SET DEFAULT 和 CASCADE。简要说明他们的工作:

RESTRICT - MASTER 表中的行只有在没有被 SERVANT 表中的任何行引用时才能被删除。

SET NULL - 删除 MASTER 表中的一行将导致 SERVANT 表中的任何 FK 设置为 NULL。

SET DEFAULT - 与设置 NULL 类似,只是 FK 设置为默认值而不是 NULL。

CASCADE - 删除 MASTER 表中的行将导致 SERVANT 表中引用已删除 MASTER 行的任何行也被删除。

要更改这些选项,您必须修改您的 create 语句以指定 on update 和 on delete 操作。

CREATE TABLE MASTER (
  _ID INTEGER PRIMARY KEY, 
  ...
);
CREATE TABLE SERVANT (
  _ID INTEGER PRIMARY KEY, 
  MASTERID INTEGER, 
  FOREIGN KEY(MASTERID) REFERENCES MASTER(_ID) ON UPDATE CASCADE ON DELETE SET NULL
);

编辑:不要忘记确保您的 SQLite 版本是使用外键支持编译的,并且您已通过指定启用它PRAGMA foreign_keys = ON;

于 2013-07-09T15:29:40.353 回答