Does SQLite really not preserve data integrity of foreign key constraints by default?
较新版本的 SQLite 支持外键约束。可以定义
1 2 3 | 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。但与其他星展银行相反,"NO ACTION"似乎并不意味着不执行删除或更新。这似乎意味着没有采取任何措施来保持完整性,至少根据我的测试(*)并且如果我理解文档正确:
Configuring"NO ACTION" means just that: when a parent key is modified
or deleted from the database, no special action is taken.
因此
1 2 3 | INSERT INTO MASTER (_ID) VALUES (1); INSERT INTO SERVANT (_ID, MASTERID) VALUES (1,1); DELETE FROM MASTER; |
给我一个空的 MASTER 表和一个 SERVANT 表,外键指向任何地方。
任何人都可以确认这种行为并解释为什么以这种方式实施吗?还是我必须配置一些东西才能使外键支持工作?
我是 SQLite 开发的新手,如果这是一个愚蠢的问题,请原谅我。
编辑:(*) 我的测试有缺陷,请参阅下面的答案。
我会尽量自己回答:
不,如果配置正确,SQLite 在这种情况下会保持数据完整性。默认情况下使用"NO ACTION",如果引用表中仍有引用键(用 3.7.x 测试),则禁止删除或更新主键。
我的错是我不知道必须为每个与数据库的新连接配置
编辑:我认为 SQLite 文档在这里具有误导性。
你是对的。 "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 行的所有行也被删除。
要更改这些选项,您必须修改您的创建语句以指定更新和删除操作。
1 2 3 4 5 6 7 8 9 | 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 版本是使用外键支持编译的,并且您已通过指定
启用它