概述
本文档描述了对SQL外键约束的支持 引入SQLite 版本3.6.19 (2009-10-14).
第一部分介绍了 SQL外键的概念,并定义术语 用于文档的其余部分。 第2节描述了步骤 应用程序必须采用才能在中启用外键约束 SQLite(默认情况下禁用)。 下一节,第3节, 描述用户必须创建才能使用的索引 外键约束,以及为了 有效运行的外键约束。 第4节描述 SQLite和 第5节描述了 交流发电机 和 DROP表格 命令是 增强以支持外键约束。 最后,第6节 列举当前实现缺少的功能和限制。
本文档未包含所用语法的完整描述 在SQLite中创建外键约束。 这可以发现为 文档的一部分 创建表格 声明。
1 外键约束简介
SQL外键约束用于强制“存在”关系 表之间。 例如,考虑使用 以下SQL命令:
CREATE TABLE艺术家( artistid INTEGER主键, 艺人姓名文本 ); CREATE TABLE曲目( trackid整数, 轨道名称文本, 轨道艺术家INTEGER --必须映射到artist.artistid! );
使用此数据库的应用程序有权假定 中的每一行 轨道 表中存在对应的行 艺术家 表。 毕竟,声明中的评论是这样说的。 不幸的是,如果用户使用外部工具或 如果应用程序中存在错误,则可能会将行插入 轨道 不对应于 艺术家 表。 或者可以从中删除行 艺术家 桌子,离开 中的孤立行 轨道 与任何 中的其余行 艺术家 。这可能会导致应用程序 或应用程序稍后发生故障,或至少使编码 应用更加困难。
一种解决方案是向数据库添加SQL外键约束 模式以强制执行 艺术家 和 轨道 表。 为此,可以添加外键定义 通过修改 轨道 下表:
CREATE TABLE曲目( trackid整数, 轨道名称文本, 轨道艺术家INTEGER, 外键(trackartist)参考艺术家(artistid) );
这样,约束由SQLite强制执行。 正在尝试插入 划入 轨道 与任何 中的行 艺术家 表将失败,尝试也将失败 从中删除行 艺术家 存在依赖项时的表 中的行 轨道 表有一个例外:如果 中的键列 轨道 表为NULL,则没有相应的 中的条目 艺术家 表是必需的。 用SQL表示,这 意味着对于 轨道 表,如下 表达式的计算结果为true:
trackartist为空或存在(从artist中选择1,其中artisti=trackartest)
提示:如果应用程序需要更严格的 艺术家 和 轨道 ,其中不允许NULL值 在中 轨道艺术家 列,只需添加适当的 模式的“NOT NULL”约束。
有几种其他方法可以添加等效的外键声明 到 创建表格 声明。 请参阅 CREATE TABLE文档 了解详细信息。
下面的SQLite命令行会话说明了 添加到 轨道 表:
sqlite>SELECT*FROM艺术家; 艺人艺名 -------- ----------------- 1迪安·马丁 2弗兰克·辛纳特拉 sqlite>SELECT*FROM轨迹; trackid trackname轨迹艺术家 ------- ----------------- ----------- 11这是阿莫尔1 12圣诞布鲁斯1 13我的方式2 方形> --这将失败,因为插入trackartist列(3)的值 方形> --与艺术家表中的行不对应。 sqlite>插入轨道值(14,“Bojangles先生”,3); SQL错误:外键约束失败 方形> --这之所以成功,是因为向trackartist中插入了NULL。 A类 方形> --在这种情况下,不需要artist表中的相应行。 sqlite>INSERT INTO track VALUES(14,'Mr.Bojangles',NULL); 方形> --尝试修改记录的trackartist字段 方形> --been inserted也不起作用,因为trackartist(3)的新值 方形> --仍然不对应于艺术家表中的任何行。 sqlite>UPDATE track SET trackartist=3 WHERE trackname='Mr.Bojangles'; SQL错误:外键约束失败 方形> --将所需行插入艺术家表。 这样就可以 方形> --更新插入的行以将trackartist设置为3(因为相应的 方形> --艺术家表中的行现在存在)。 sqlite>插入艺术家价值观(3,‘小萨米·戴维斯’); sqlite>UPDATE track SET trackartist=3 WHERE trackname='Mr.Bojangles'; 方形> --现在,“Sammy Davis Jr.”(artistid=3)已添加到数据库中, 方形> --可以使用此艺术家插入新曲目,而不会违反 sqlite公司> --外键约束: sqlite>插入曲目值(15,“Boogie Woogie”,3);
正如您所期望的那样,不可能将数据库操作到某个状态 通过删除或更新 艺术家 表或:
方形> --尝试删除“Frank Sinatra”的艺术家记录失败,因为 方形> --跟踪表包含引用它的行。 sqlite>从艺术家删除WHERE artistname='Frank Sinatra'; SQL错误:外键约束失败 方形> --删除曲目表中指向艺术家的所有记录 方形> --“弗兰克·辛纳屈”。 只有这样才能删除艺术家。 sqlite>DELETE FROM track WHERE trackname='My Way'; sqlite>从艺术家删除WHERE artistname='Frank Sinatra'; 方形> --尝试在artist表中更新行的artistid 方形> --跟踪表中存在引用它的记录。 sqlite>UPDATE artist SET artistid=4 WHERE artistname='Dean Martin'; SQL错误:外键约束失败 方形> --一旦所有引用艺术家表中某行的记录都有 方形> --删除后,可以修改行的artistid。 sqlite>DELETE FROM track WHERE trackname IN('That’s Amore','Christmas Blues'); sqlite>UPDATE artist SET artistid=4 WHERE artistname='Dean Martin';
SQLite使用以下术语:
这个 父表 是一个外键约束的表 参考。本节示例中的父表是 艺术家 表。 一些书籍和文章将其称为 被引用的表 ,这可能更正确,但往往 导致混乱。
这个 子表 是一个外键约束的表 应用于和包含REFERENCES子句的表。 本节中的示例使用 轨道 桌子 作为子表。 其他书籍和文章将此称为 参考表格 .
这个 父关键字 是父级中的列或列集 外键约束引用的表。这通常是,但 并非总是父表的主键。 父密钥必须 是父表中的一个或多个命名列,而不是 罗伊德 .
这个 子密钥 是子级中的列或列集 受外键约束约束的表,并且 保留REFERENCES子句。
如果子表中的每一行都满足外键约束 一个或多个子键列为NULL,或者存在 父表中每个父键列都包含值的行 等于其关联子键列中的值。
在上段中,当值为 使用规则进行比较 明确规定 在这里 以下澄清适用:
2 启用外键支持
为了在SQLite中使用外键约束,库必须 编译时两者都不使用 SQLITE_OMIT_foregin_KEY(SQLITE_OMIT_foregin_KEY) 也不是 SQLITE_OMIT_TRIGGER公司 定义。 如果定义了SQLITE_OMIT_TRIGGER 但SQLITE_OMIT_FOREIGN_KEY不是,那么SQLITE的行为与以前一样 到 版本3.6.19 (2009-10-14) -外键定义被解析,可能是 使用查询 PRAGMA外语_密钥_列表 ,但外键约束 没有强制执行。 这个 PRAGMA外文_键 命令在此中是no-op 配置。 如果定义了OMIT_FOREIGN_KEY,则外键 甚至无法解析定义(试图指定外部 键定义是一个语法错误)。
假设在启用了外键约束的情况下编译库, 它仍然必须由应用程序在运行时使用 PRAGMA外文_键 命令。 例如:
sqlite>PRAGMA foreign_keys=ON;
默认情况下禁用外键约束 (用于向后兼容), 因此必须分别为每个 数据库连接 . (但请注意,SQLite的未来版本可能会发生变化 因此,默认情况下启用外键约束。 小心 开发人员不会 对是否启用外键进行任何假设 默认设置,但将根据需要启用或禁用它们。) 应用程序还可以使用 PRAGMA外文_键 对的声明 确定当前是否启用了外键。 以下内容 命令行会话演示了这一点:
sqlite>PRAGMA foreign_keys; 0 sqlite>PRAGMA foreign_keys=ON; sqlite>PRAGMA foreign_keys; 1 sqlite>PRAGMA foreign_keys=关闭; sqlite>PRAGMA foreign_keys; 0
提示:如果命令“PRAGMA foreign_keys”没有返回任何数据,而是返回 包含“0”或“1”的单行,然后是您所在的SQLite版本 using不支持外键(可能是因为它早于 3.6.19或因为它是用编译的 SQLITE_OMIT_FOREIGN_KEY数据库 或 SQLITE_OMIT_TRIGGER公司 定义)。
无法启用或禁用外键约束 在中间 多阶段交易 (当SQLite 不在中 自动提交模式 ). 尝试这样做不会返回 错误; 它根本没有效果。
三。 必需和建议的数据库索引
通常,外键约束的父键是的主键 父表。 如果它们不是主键,则父键 列必须共同受UNIQUE约束或具有 a唯一索引。 如果父键列具有UNIQUE索引, 则该索引必须使用指定的排序规则序列 在父表的CREATE TABLE语句中。 例如,
CREATE TABLE父项(一个主键,b UNIQUE,c,d,e,f); 在父项(c,d)上创建唯一索引i1; 在父项(e)上创建索引i2; 在父级上创建唯一索引i3(f COLLATE nocase); CREATE TABLE child1(f,g REFERENCES parent(a)); --好的 创建表child2(h,i引用父项(b)); --好的 创建表child3(j,k,外键(j,k)引用父项(c,d)); --好的 CREATE TABLE child4(l,m REFERENCES parent(e)); --错误! CREATE TABLE child5(n,o REFERENCES父级(f)); --错误! 创建表child6(p,q,外键(p,q)引用父项(b,c)); --错误! CREATE TABLE child7(r REFERENCES parent(c)); --错误!
作为表的一部分创建的外键约束 孩子1 , 孩子2 和 孩子3 都很好。 外键 声明为表的一部分 孩子4 是一个错误,因为即使 父键列被索引,索引不是UNIQUE。 表的外键 孩子5 是一个错误,因为即使父键列具有唯一的 索引时,索引使用不同的排序序列。 桌子 孩子6 和 孩子7 不正确,因为while 它们的父键上都有UNIQUE索引,这些键不是 与单个UNIQUE索引的列完全匹配。
如果数据库架构包含需要查找的外键错误 如果要识别多个表定义,则这些错误不是 创建表时检测到。 相反,这些错误会阻止 应用程序准备修改内容的SQL语句 以使用外键的方式创建子表或父表。 更改内容时报告的错误是“DML错误”和错误 架构更改时报告的是“DDL错误”。 换句话说,错误配置的外键约束要求 查看子级和父级都是DML错误。 外键DML错误的英语错误消息通常是 “外键不匹配”,但如果父项 表不存在。 如果出现以下情况,则会报告外键DML错误:
父表不存在,或 外键约束中命名的父键列do 不存在,或 外键约束中命名的父键列不是 父表的主键,并且不受唯一 使用CREATE TABLE中指定的排序序列的约束,或 子表引用父表的主键,但没有 指定主键列和主键数 父级中的列与子键列的数量不匹配。
上面的最后一个项目符号如下所示:
创建表parent2(a,b,主键(a,b)); CREATE TABLE child8(x,y,FOREIGN KEY(x,y)REFERENCES parent2); --好的 CREATE TABLE child9(x REFERENCES parent2); --错误! CREATE TABLE child10(x,y,z,外键(x,y,z)引用parent2); --错误!
相比之下,如果仅通过查找即可识别外键错误 在子表的定义中,不必查询 父表定义,然后 创建表格 子表的语句失败。 因为错误 在架构更改期间发生,这是DDL错误。 无论何种情况,都会报告外键DDL错误 当 表已创建。
子键列不需要索引,但它们几乎 总是有益的。 返回 中的示例 第1部分 ,每次应用程序 从 艺术家 表(父表),它 执行与以下SELECT语句等效的搜索 用于引用中的行 轨道 表(子表)。
从track中选择rowid WHERE trackartist=?
在哪里? 中的替换为 艺术家 要从中删除的记录的列 艺术家 表格(召回 那个 轨道艺术家 列是子键 艺术家 列是父键)。 或者,更一般地说:
从<child-table>WHERE<child-key>=:parent_key_value选择行ID
如果此SELECT返回任何行,则SQLite得出以下结论 从父表中删除行将违反外键 约束并返回错误。 如果父键的内容 修改或将新行插入父表。 如果这些查询不能使用索引,则必须执行 对整个子表进行线性扫描。 在非普通数据库中,这可能 昂贵得令人望而却步。
因此,在大多数实际系统中,应该在子键列上创建索引 每个外键约束的。 子键索引没有 成为(通常不会成为)唯一索引。 再次回到第1节中的示例 高效实现外键的完整数据库模式 约束可能是:
CREATE TABLE艺术家( artistid INTEGER主键, 艺人姓名文本 ); CREATE TABLE曲目( trackid整数, 轨道名称文本, trackartist INTEGER参考艺术家 ); CREATE INDEX trackindex ON track(轨迹艺术家);
上面的块使用速记形式创建外键约束。 附上“参考 <父表> “子句到列 定义创建一个外键约束,该约束将列映射到 的主键 <父表> 。请参阅 创建表格 有关更多详细信息的文档。
4 高级外键约束功能
4.1. 复合外键约束
复合外键约束是子键和父键 都是复合键。 例如,考虑 以下数据库架构:
CREATE TABLE相册( 白蛋白艺术家TEXT, albumname文本, 二元albumcover, 主键(albumartist,albumname) ); CREATE TABLE歌曲( songid整数, 歌曲艺术家文本, 歌曲集文本, 歌曲名文本, 外键(歌曲艺术家,歌曲专辑)参考专辑(专辑艺术家,专辑名称) );
在这个系统中,歌曲表中的每个条目都需要映射到一个条目 在相册表中使用相同的艺术家和相册组合。
父键和子键必须具有相同的基数。 在SQLite中,如果有任何子键列(在本例中为songartist 和songabum)为NULL,则不需要相应的 父表中的行。
4.2. 延迟的外键约束
SQLite中的每个外键约束都被分类为立即数 或延期。 默认情况下,外键约束是直接的。 提供的所有外键示例 迄今为止,一直存在着直接的外键限制。
如果一个语句修改了数据库的内容 外键约束违反了语句的结论, 抛出异常,并且 语句的效果将恢复。 相比之下,如果 语句修改数据库的内容,以便 违反了外键约束,未报告违反情况 立即。 未检查延迟的外键约束 直到事务尝试 承诺 . 只要用户有 一个打开的事务,允许数据库以以下状态存在 违反了任意数量的延迟外键约束。 然而, 承诺 只要外键约束保持在 违反。
如果当前语句不在显式事务( 开始 / 承诺 / 回降 块),然后是隐式 事务已提交 只要语句执行完毕。 在这种情况下,延期 约束的行为与直接约束相同。
要将外键约束标记为延迟,其声明必须 包括以下条款:
指定外键约束的完整语法作为一部分提供 的 创建表格 文档。 替换上面的短语 具有以下任一项 创建直接外键约束。
不可延期初始延期 --直接外键约束 最初不可立即延期 --直接外键约束 不可延期 --直接外键约束 可延迟初始立即 --直接外键约束 可延期 --直接外键约束
这个 defer_foreign_keys杂注 可用于临时更改所有外来 要延迟的键约束,无论它们是如何声明的。
下面的示例说明了使用延迟外文的效果 键约束。
--数据库架构。 这两个表最初都是空的。 CREATE TABLE艺术家( artistid INTEGER主键, 艺人姓名文本 ); CREATE TABLE曲目( trackid整数, 轨道名称文本, trackartist INTEGER参考艺术家(artistid) 可延期初始延期 ); sqlite3> --如果外键约束是立即的,则此INSERT将 方形3> --导致错误(因为在表artist中没有行 方形3> --artisti=5)。 但随着约束被推迟 方形3> --打开事务,没有发生错误。 sqlite3>开始; sqlite3>插入轨道值(1,“白色圣诞节”,5); 方形3> --以下COMMIT失败,因为数据库处于以下状态 方形3> --不满足延迟的外键约束。 这个 方形3> --交易仍处于打开状态。 sqlite3>提交; SQL错误:外键约束失败 方形3> --在artisti=5的artist表中插入一行后 方形3> --满足延迟的外键约束。 那就有可能了 方形3> --以无错误地提交事务。 sqlite3>插入艺术家价值观(5,“Bing Crosby”); sqlite3>提交;
A类 嵌套保存点 交易可以在 数据库处于不满足延迟外键的状态 约束。 事务保存点(一个非嵌套的保存点 当前没有打开的事务时打开),在 另一方面,受到与COMMIT相同的限制-尝试 在数据库处于这种状态时释放它将失败。
如果COMMIT语句(或事务SAVEPOINT的RELEASE)失败 因为数据库当前的状态违反了延迟 外键约束,并且当前存在 嵌套保存点 ,嵌套的保存点保持打开状态。
4.3. ON DELETE和ON UPDATE操作
外键ON DELETE和ON UPDATE子句用于配置操作 从父表中删除行时发生(ON DELETE),或 修改现有行的父键值(ON UPDATE)。 一张单人床 外键约束可以为ON DELETE配置不同的操作 和ON UPDATE。 外键操作在许多方面与触发器类似。
与中的每个外键关联的ON DELETE和ON UPDATE操作 SQLite数据库是“NO ACTION”、“RESTRICT”、“SET NULL”、, “设置默认值”或“级联”。 如果未显式指定操作 默认为“无操作”。
无操作 :配置“NO ACTION”意味着:当 父密钥已从数据库中修改或删除,没有特殊操作 拿。
限制 :“限制”操作意味着应用程序 禁止删除(对于ON DELETE RESTRICT)或修改 (对于ON UPDATE RESTRICT)存在一个或多个子项时的父项 映射到它的键。限制效果之间的差异 操作和常规外键约束强制是 字段更新后立即进行RESTRICT操作处理- 而不是在当前语句的末尾 约束,或在当前事务结束时 延迟的约束。 即使是外键约束 附加到被延迟,配置RESTRICT操作会导致SQLite 如果具有从属子键的父键为 删除或修改。
设置为空 :如果配置的操作为“SET NULL”,则当 父密钥被删除(对于ON DELETE SET NULL)或修改(对于ON UPDATE SET NULL),子表中所有行的子键列 映射到父键的设置为包含SQL NULL值。
设置默认值 :“SET DEFAULT”操作类似于 “设置为空”, 除了每个子键列都被设置为包含列的 默认值而不是NULL。 请参阅 创建表格 有关如何将默认值分配给表的详细信息的文档 柱。
级联 :“CASCADE”操作传播删除或更新 对每个从属子键的父键进行操作。 对于“ON” DELETE CASCADE”操作,这意味着子表中的每一行 与已删除父行关联的也将被删除。 对于“ON” UPDATE CASCADE”操作,这意味着存储在每个依赖项中的值 修改子键以匹配新的父键值。
例如,将“ON UPDATE CASCADE”子句添加到外键 如下所示增强了第1节中的示例模式,以允许用户 更新artistid(外键约束的父键) 列而不破坏引用完整性:
--数据库架构 CREATE TABLE艺术家( artistid INTEGER主键, 艺人姓名文本 ); CREATE TABLE轨道( trackid整数, 轨道名称文本, 轨道艺术家INTEGER参考艺术家(艺术家) 关于更新级联 ); sqlite>SELECT*FROM艺术家; 艺人艺名 -------- ----------------- 1迪安·马丁 2弗兰克·辛纳特拉 sqlite>SELECT*FROM曲目; trackid trackname轨迹艺术家 ------- ----------------- ----------- 11那是阿莫里1 12圣诞布鲁斯1 13我的方式2 sqlite公司> --更新“Dean Martin”艺术家记录的artistid栏。 方形> --通常,这会产生一个约束,因为它会孤立这两个 方形> --跟踪表中的相关记录。 然而,ON UPDATE CASCADE子句 方形> --附加到外键定义导致更新为“级联” 方形> --以防止外键约束冲突。 sqlite>UPDATE artist SET artistid=100 WHERE artistname='Dean Martin'; sqlite>SELECT*FROM艺术家; 艺人艺名 -------- ----------------- 2弗兰克·辛纳特拉 100迪安·马丁 sqlite>SELECT*FROM曲目; trackid trackname轨迹艺术家 ------- ----------------- ----------- 11这是Amore 100 12圣诞布鲁斯100 13我的路2
配置ON UPDATE或ON DELETE操作并不意味着 键约束不需要满足。 例如,如果 配置了“ON DELETE SET DEFAULT”操作, 但父表中没有行 对应于子键列的默认值,删除 存在从属子键时父键仍会导致外键 违反。 例如:
--数据库架构 CREATE TABLE艺术家( artistid INTEGER主键, 艺人姓名文本 ); CREATE TABLE曲目( trackid整数, 轨道名称文本, 轨迹艺术家INTEGER 默认值0 参考艺术家(artistid) 删除集合默认值时 ); sqlite>SELECT*FROM艺术家; 艺人艺名 -------- ----------------- 3小萨米·戴维斯。 sqlite>SELECT*FROM曲目; trackid trackname轨迹艺术家 ------- ----------------- ----------- 14 Bojangles先生3 方形> --从父表中删除行会导致子键 方形> --要设置为整数值0的从属行的值。 然而,这 方形> --值与父表中的任何行都不对应。 因此 方形> --违反了外键约束并引发了is异常。 sqlite>从艺术家删除WHERE artistname='Sammy Davis Jr.'; SQL错误:外键约束失败 方形> --这一次,值0确实对应于父表行。 而且 sqlite公司> --因此DELETE语句不会违反外键约束 方形> --并且没有抛出异常。 sqlite>插入艺术家值(0,“未知艺术家”); sqlite>从艺术家删除WHERE artistname='Sammy Davis Jr.'; sqlite>SELECT*FROM艺术家; 艺人艺名 -------- ----------------- 0未知艺术家 sqlite>SELECT*FROM曲目; trackid trackname轨迹艺术家 ------- ----------------- ----------- 14 Bojangles先生0
熟悉的人 SQLite触发器 会注意到 上面示例中演示的“ON DELETE SET DEFAULT”操作是 与以下AFTER DELETE触发器的效果类似:
在艺术家开始删除后创建触发器on_delete_set_default 更新子集合trackartist=0 WHERE trackartir=old.artistid; 结束;
每当删除外键约束的父表中的行时, 或者修改存储在父键列中的值时, 事件的逻辑顺序是:
执行适用的BEFORE触发程序, 检查本地(非外键)约束, 更新或删除父表中的行, 执行任何必需的外键操作, 执行适用的AFTER触发程序。
ON-UPDATE外键操作和 SQL触发器。 只有在 修改父键,以便新的父键值 不等于老年人。 例如:
--数据库架构 CREATE TABLE父项(x主键); CREATE TABLE子项(y在更新集为NULL时引用父项); sqlite>SELECT*FROM父级; x个 ---- 钥匙 sqlite>SELECT*FROM子级; 年 ---- 钥匙 方形> --由于以下UPDATE语句实际上并没有修改 方形> --父键值,则不会执行ON UPDATE操作,并且 方形> --子键值未设置为NULL。 sqlite>UPDATE父SET x='key'; sqlite>SELECT IFNULL(y,'null')FROM子级; 年 ---- 钥匙 方形> --这一次,因为UPDATE语句确实修改了父键 方形> --值,则执行ONUPDATE操作并设置子键 sqlite公司> --设置为NULL。 sqlite>UPDATE父SET x='key2'; sqlite>SELECT IFNULL(y,'null')FROM子级; 年 ---- 无效的
5 CREATE、ALTER和DROP TABLE命令
本节描述了 创建表格 , ALTER表格 , 和 DROP表格 命令 与SQLite的外键交互。
A类 创建表格 命令的操作与否相同 已启用外键约束 。的父键定义 创建表时不检查外键约束。 有 没有什么可以阻止用户创建一个外键定义 引用不存在的父表,或引用 不存在或不受主键或唯一的共同约束 约束。
这个 ALTER表格 在国外,命令在两个方面的工作方式不同 关键约束已启用:
如果在准备时启用了外键约束,则 DROP表格 命令执行隐式 删除 删除所有 删除表之前从表中删除行。隐式DELETE不会导致 任何要触发的SQL触发器,但可能会调用外键操作或约束 违规行为。 如果违反了直接外键约束,则DROP TABLE语句失败,表未被删除。 如果延期外国 违反了键约束,则在用户尝试时报告错误 如果仍然违反外键约束,则提交事务 在那一点上存在。 作为一部分,遇到任何“外键不匹配”错误 将忽略隐式DELETE的。
这些增强功能的目的是 ALTER表格 和 DROP表格 命令是为了确保它们不能用于创建 包含外键冲突,至少外键约束是 启用。 但这条规则有一个例外。 如果父键为 不受作为 父表定义,但受制于UNIQUE约束 使用 创建索引 命令,然后是子级 可以填充表而不会导致“外键不匹配”错误。 如果 从数据库模式中删除UNIQUE索引,然后删除父表 本身被丢弃,不会报告任何错误。 然而,数据库可能 处于外键约束的子表包含 不引用任何父表行的行。 这种情况可以避免 如果数据库架构中的所有父键都受PRIMARY KEY约束 或作为父表定义的一部分添加的UNIQUE约束,而不是 通过外部UNIQUE索引。
的属性 DROP表格 和 ALTER表格 描述的命令 以上仅适用于启用外键的情况。 如果用户认为 不受欢迎,那么解决方法是使用 PRAGMA外文_键 至 在执行DROP或ALTER TABLE之前禁用外键约束 命令。 当然,虽然外键约束被禁用,但什么都没有 阻止用户违反外键约束,从而创建 内部不一致的数据库。
6 限制和不支持的功能
本节列出了一些限制和省略的功能 其他地方提到的。
不支持MATCH子句。 根据SQL92,MATCH子句 可以附加到复合外键定义以修改方式 处理子键中出现的NULL值。 如果“MATCH SIMPLE”为 指定,则不需要子键来对应任何行 如果一个或多个子键值为NULL,则返回父表的。 如果指定了“MATCH FULL”,则如果任何子键值为 NULL,父表中不需要相应的行,但所有 子键值必须为NULL。 最后,如果外键约束 声明为“MATCH PARTIAL”,其中一个子键值为NULL, 父表中必须至少存在一行 非NULL子键值与父键值匹配。
SQLite解析MATCH子句(即不报告语法错误 如果指定了一个),但不强制执行它们。 所有外键 SQLite中的约束处理方式就像指定了MATCH SIMPLE一样。
不支持在延迟和立即之间切换约束 模式。 许多系统允许用户切换单个外键 之间的约束 推迟 和立即 模式(例如使用Oracle“SET CONSTRAINT”命令)。 SQLite不支持此功能。 在SQLite中,外键约束是 创建时永久标记为延迟或立即。
外键操作的递归限制。 这个 SQLITE_MAX_TRIGGER_DEPTH公司 和 SQLITE_LIMIT_TRIGGER_DEPTH公司 设置确定触发器的最大允许深度 程序递归。 就这些限制而言, 外键操作 被认为是触发程序。 这个 PRAGMA递归触发器 设置不影响操作 外键操作。 无法禁用递归外部 关键行动。
外键不能跨越架构边界。 也就是说,在 参考文献(X.Y)
桌子 X(X)
只能解决 在包含 参考文献
条款。
此页面上次修改时间 2024-01-23 13:08:17 联合技术公司