Sqlite   发布时间:2022-05-22  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了SQLite 外键支持大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
sqlite 外键支持
目录
1简介foreign key 约束
2支持外键
3要求和建议的索引
4高级foreign key 约束特性
41组合foreign key 约束
42延迟的foreign key 约束
43ON deletE 和ON updatE 操作
5CREATE,ALTER 和drop table 命令
6限制和不支持的功能

概述

此文档介绍了支持为sqlite 版本3中引入sql foreign key 约束619

这个过程的最后一节介绍的概念sql 外键按照示例和定义用于配置角色和资源设置的用户界面它为该文档的其余部分部分2介绍了应用程序必须采取的步骤在sqlite 为了启用foreign key 约束(默认情况下,它被禁用default)下一小节第4节介绍"索引对象必须创建in order to use foreign key 约束和那些被创建在高效的foreign key 约束第4部分说明sqlite 支持的高级外键相关的功能和节5介绍了方式ALTER和drop table命令的增强,支持foreign key 约束最后,部分6枚举丢失当前实现的功能和限制

此文档未包含完整的说明在sqlite @R_616_9899@foreign key 约束的语法可以找到此文档的一部分create table语句.

1简介foreign key 约束

sql foreign key 约束是用于强制"exists "关系琛ㄤ箣闂寸殑鍏崇郴例如,请虑使用以下sql 命令创建的数据库模式:

create table artist( 
artistID INTEGER PRIMARY KEY,artist@R_749_4687@T 
);
create table track( 
曲目长度IntegeR,track@R_749_4687@T,trackartist IntegeR -- 必须映射到一个艺术家artistID!
);

使用该数据库的应用程序可以再运行该产品n次&假设在每一行的跟踪表存在有相应行中艺术家表在声明说,这样所有之后,注释不幸的是,如果用户后来使用外部工具或数据库中如果有可能在应用程序中的BUG,行插入到跟踪表没有与任何行艺术家表或工作表中的行可能会被删除艺术家在指定的表,孤立行跟踪表没有与任何剩余的行中艺术家这可能会导致应用程序或应用程序以更高版本,或者至少使编写应用程序更困难

向数据库添加一个sql foreign key 约束架构来强制之间的关系艺术家跟踪表要完成这项操作,添加了一个外键定义可以通过修改的声明跟踪表向以下操作之一:

create table track( 曲目长度IntegeR,trackartist IntegeR,FOREIGN KEY(trackartist) REFERENCES artist(artistID ) );

按照这种方式,在约束是由sqlite 实施正在试图将到行跟踪表包含任何不对应的行艺术家表就会失败,则会在试图删除区域.艺术家发生存在依赖行在表跟踪表有一点例外: 如果外键列中跟踪表被NulL,然后在没有相应的条目艺术家表是必需的用sql,这意味着的每行的行号跟踪表,下面的表达式的计算结果为true :

trackartist IS NulL OR EXISTS(SELECT 1FROM 艺术家WHERE artistID=trackartist )

提示: 如果应用程序需要更严格之间的关系艺术家跟踪,其中NulL 值中不允许使用功能trackartist列,只需将适当的"NOT NulL 约束到方案的名称.

有几种其他方法添加等效外键声明一个create table语句请参阅create table 文档有关详细内容.

可以使用下面的sqlite 命令行举例说明了外部键约束的效果在添加到跟踪表:

sqlite > SELECT *FROM 艺术家; artistID artistname -------- ----------------- 1: marTin 2弗兰克sinatra sqlite > SELECT *FROM 跟踪; 曲目长度trackname trackartist ------- ----------------- ----------- 11 的amore 1 圣诞节12 蓝色1 13 2的方法 sqlite > -- 此失败,原因是该值插入到trackartist (3) sqlite > -- 行中不对应的艺术家表. sqlite > INSERT INTO 跟踪VALUES(14,''mrbojangles '',3) ; sql 错误: foreign key 约束失败 sqlite > -- 此操作成功,因为一个NulL 被插入到trackartist一个 sqlite > -- 相应行中在这种情况下表中不是必需的艺术家 sqlite > INSERT INTO 跟踪VALUES(14,''mrbojangles ",null); sqlite > 试图修改字段的trackartist -- 之后的记录 sqlite > -- 将修改不工作,因为新trackartist 的值(3) sqlite > -- 问题仍然没有对应于表中的艺术家的任何行 sqlite > updatE 跟踪SET trackartist =3WHERE trackname =''mrbojangles '' ; sql 错误: foreign key 约束失败 sqlite > -- 插入所需的行复制到的艺术家表因此,从 sqlite > -- 更新插入的行trackartist 设成3(自一个对应的 sqlite > -- 行在表格的艺术家exists) . sqlite > INSERT INTO 艺术家VALUES(3,'��AMMy davis breeze 5.1'') ; sqlite > updatE 跟踪SET trackartist =3WHERE trackname =''mrbojangles '' ; sqlite > -- 现在,"sAMMy davis breeze 5.1" (artistID =3)已被添加到数据库中, sqlite > -- 它可以INSERT 新的跟踪此艺术家的使用,而不asset sqlite > -- 外键约束: sqlite > INSERT INTO 跟踪VALUES(15,''boogIE woogIE '',3) ;

正如你所期待的,不能添加到数据库中的操作向加快外键约束的状态通过删除或更新行艺术家表请执行以下任一操作:

sqlite > 试图删除"frank 的艺术家记录-- sinatra "失败,因为 sqlite > -- 跟踪表引用它保持一个行 sqlite > deletE FROM 艺术家WHERE artistname =''frank sinatra '' ; sql 错误: foreign key 约束失败 sqlite > -- 删除所有记录,从"跟踪表引用艺术家 sqlite > -- "frank sinatra "只是然后有删除的艺术家 sqlite > deletE FROM 跟踪WHERE trackname =''my 方式'' ; sqlite > deletE FROM 艺术家WHERE artistname =''frank sinatra '' ; sqlite > -- 尝试更新artistID 艺术家表中的某行在 sqlite > -- 是否存在跟踪表引用它的记录. sqlite > updatE 艺术家SET artistID=4 WHERE artistname =''dean marTin '' ; sql 错误: foreign key 约束失败 sqlite > -- 一旦所有引用中的某行的记录表中的示例是艺人 sqlite > -- 被删除,则不会修改行的artistID sqlite > deletE FROM 跟踪WHERE trackname IN( ''That "的amore '',''christmas 蓝色'') ; sqlite > updatE 艺术家SET artistID=4 WHERE artistname =''dean marTin '' ;

sqlite 使用以下术语:

  • "父表为表中的一个foreign key 约束引用父表在本节中的示例是艺术家表某些引用这个作为这台计算机的书籍和项目引用的表它不支持截然不同正确,但sql server 会造成混淆

  • "将子表是应用于和一个foreign key 约束的表该表包含REFERENCES 子句本节中的示例使用跟踪表的子表其他的书籍和文章引用这个作为这台计算机引用表.

  • "父键为一列或一组列在父表中指向的外键约束这是通常,但并不总是父表中的主键父键列必须命名为列或在父表中有关详细信息,未对id.

  • "子键为一列或一组列在子表中所由foreign key 约束和该保持REFERENCES 子句的一部分.

如果满足外键约束,在子表中每一行的一个或多个子键的列NulL,或theta (父表中的某行的每个父键列含有一个值,该值等于该值与其相关联的子键列.

在上面的段落,"equal 术语"表示相等比较值是使用规则这里指定的下面的说明:

  • 当比较文本值,比较顺序总是使用父键列关联.

  • 当比较值,如果父键列有一相似性一个应用了相似性,然后指向子关键字值结果.

2支持外键

为了在使用foreign key 约束必须使用的库拥有"添加项"sqlite,两者都不@R_748_5607@OMIT_FOREIGN_KEY或@R_748_5607@OMIT_trigGER定义如果@R_748_5607@OMIT_trigGER 但@R_748_5607@OMIT_FOREIGN_KEY 未被定义,然后sqlite 的行为方式为它之前版本36解析并可能19 -外键定义后将查询的使用PRAGMA foreign_key_list未实施,但foreign key 约束"PRAGMA foreign_keys输出是一个no-op 在此配置如果OMIT_FOREIGN_KEY 被定义,然后外键定义不能解析concurrenthashmap (试图指定一个外部键定义是语法error)

启用假定使用的库编译的foreign key 约束,它必须还是启用的应用程序在运行时,使用PRAGMA foreign_keys命令例如:

sqlite > PRAGMA foreign_keys =ON;

默认情况下禁用外部键约束(为了改善compatibility),因此必须启用所有分类汇总和总计数据库连接单独购买(.但是,请注意.以后的版本中得到的sqlite 可能会更改,以便foreign key 约束(默认情况下启用)仔细地开发人员将不进行任何草稿是否外键的缺省情况下是启用的,但会而启用或禁用它们以必要的")将应用程序从还可以使用PRAGMA foreign_keys当前被启用语句,以确定是否外键可以使用下面的命令行演示了该:

sqlite > PRAGMA foreign_keys ; 0 sqlite > PRAGMA foreign_keys =ON; sqlite > PRAGMA foreign_keys ; 1 sqlite > PRAGMA foreign_keys =OFF; sqlite > PRAGMA foreign_keys ; 0

提示: 如果命令"PRAGMA foreign_keys "返回任何数据,而不是单个行包含"0 "或"1 "然后您正在使用的sqlite 不支持的版本外键(因为比3619,因为它已被使用@R_748_5607@OMIT_trigGERdefined) .

不能启用或禁用检查约束试试multi-statement 事务(sqlite 时不在autocommit 模式)尝试这样做不返回一个错误;它只是没有作用

3要求和建议的索引

通常,父键的foreign key 约束是父表中的主键如果没有主键,然后父键列必须是UNIQUE 份额将受到约束或UNIQUE 索引如果父键列有一个UNIQUE 索引,则此索引时,必须使用中指定的排序规则序列都create table 语句的父表例如,

create table parent(a PRIMary KEY,bUNIQUE,c、d、e、f) ; CREATE UNIQUE INDEX i1 ON parent(c,d) ; CREATE INDEX i2 ON parent(E) ; CREATE UNIQUE INDEX i3 ON parent(f ColLATE nocasE) ; create table child1(f,gREFERENCES parent(a)) ;-- "确定" create table child2(h,我REFERENCES parent(b)) ;-- "确定" create table child3(j,k,FOREIGN KEY(j,k)REFERENCES parent(c,d)) ;-- "确定" create table child4(l,mREFERENCES parent(E)) ;-- 错误! create table child5(n,oREFERENCES parent(f)) ;-- 错误! create table child6(p 、q、FOREIGN KEY(p,q)REFERENCES parent(b,C)) ;-- 错误! create table child7(r REFERENCES parent(C)) ;-- 错误!

创建作为表的一部分在foreign key 约束子1,子3子3是否所有精细此外键声明为表的一部分child4是一个错误,因为即使父键列是索引,但由于索引不是UNIQUE表的外键child5是一个错误,因为即使父键列具有唯一的索引.索引使用不同的比较顺序表child6child7是否不正确,因为在同时UNIQUE 的索引在它们的父密钥,则不精确匹配键以单个UNIQUE 的列索引

在"名称"文本框包含外部键错误需要在多个表的定义,用于标识,然后当创建不检测这些错误相反,这种错误阻止应用程序准备sql 语句的信息,这种语句用于修改内容在子节或父表中的外键.可将它使用当内容是所报告的单独更改都将"DML 错误"和报告了错误在架构中的更改都将"DDL 错误"因此,换句话说,需要配置不当foreign key 约束面临两个子级和父都将DML 错误外键的英语语言错误消息DML 通常是"foreign 密钥不匹配错误",但也可以"no 中table "如果父表不存在外键报告可能会如果DML 错误:

  • 父表不存在,或
  • 父键列名为在外部键约束不存在,或
  • 名为在外部键约束的父键列都不父表中的主键和不受在create 指定唯一的约束使用比较顺序table,或
  • 将子表引用当前的父而不指定的主键主键列并在父主键列的数目与子键列不匹配

对上面最后项目符号是由如下:

create table parent2(a,b,PRIMary KEY(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,FOREIGN KEY(x,z) REFERENCES parent2) ; 相比之下,如果外键错误可识别只需支付的子表.而不必定义有关详情,请查阅父表定义,然后create table语句的子表失败因为错误过程中发生更改架构,这是一个DDL 错误外键DDL 报告了错误都被启用,而不管其foreign key 约束当表已被创建

用于分隔索引没有子键列所必需的,但它们几乎都是有益返回中的示例节1每次从应用程序中删除一个行,艺术家表(在父tablE) 中,可以执行下列值SELECT 语句来搜索行,如清单3所示跟踪表(在子tablE)

SELECT 未对ID FROM 跟踪WHERE trackartist =?

何处? 在上面的替换为的值artistID如果已经从列.艺术家表(4:trackartist列,而这是子级中的键artistID列,而这是父key)或者,较常:

SELECT 未对ID FROM < child-table > WHERE < child-key > =: parent_key_value

如果此SELECT 返回任何行all,然后在sqlite 结束处删除该行从父表降级,foreign key 约束,然后返回一个错误可能需要运行相似查询如果父键的内容被修改或一个到父表中插入新行如果这些查询不能使用点"."获得脚本来源,他们被迫线性扫描整个子表在Non-trivial 数据库中,这可能prohibitively 昂贵

所以,在大多数系统,应创建一个索引在子键的列每个foreign key 约束要(子键索引没有通常将不会被)UNIQUE 索引返回到部分中的示例1.那么完成高效的数据库模式的实现foreign key 约束可能是:

div class="codeblock c13" style="Font-family:宋体,trackartist IntegeR REFERENCES 艺术家 ); CREATE INDEX trackindex ON track(trackartist) ;

上面的块使用一个简写形式创建外键约束附加"REFERENCES< parent-table >为列定义"条款创建了一个外部键约束映射到主键列中的单元格.< parent-table >请参阅create table文档以获得更多的细节,

4高级foreign key 约束特性

41组合foreign key 约束

复合foreign key 约束是一个独立的子级和父键同时访问数组元素例如,请虑以下数据库模式:

create table album( 专辑艺人TEXT,album@R_749_4687@T,albumcover BINARY,PRIMary KEY(albumartist,albumname ) ); create table song( songid integer,songartist text,songalbum TEXT,song@R_749_4687@T,FOREIGN KEY(songartist,songalbum )REFERENCES album(albumartist,albumname ) );

在该系统中,每个条目的歌曲表被映射到相册中的输入项所需的表具有相同艺术家和专辑的组合

父和子键必须具有相同的基数在sqlite如果任何子键的列(在本例中songartist 和songalbum )NulL然后没有父表的一个相应行中要求

42延迟的foreign key 约束

每个外键约束sqlite 分类为即时或延迟外部键约束是需要立即默认情况下所有外键例子指定到目前为止已被直接的foreign key 约束

如果一个语句修改该数据库的内容,以便可以在违反外键约束已被该语句时将引发异常和语句效果的恢复相比之下,如果一个语句修改的内容该数据库,导致延迟foreign key 约束是立即违反了该违规行为,未报告延迟foreign key 约束将被禁用,直到事务的尝试COMMIT对于只要用户具有的事务状态,无法丢失在外键中包含任意数目的延迟的foreign key 约束但是,COMMIT将失败只要foreign key 约束冲突的web 页.

如果当前语句不显式的事务内部的(aBEGIN/COMMIT/ROLLBACKblock) 事务,然后隐式一旦完成执行该语句在这种情况下推迟约束即时相同约束

将外键约束作为声明的延迟,必须包含以下子句:

DEFERRABLE INITIALLY DEFERRED -- 延迟foreign key 约束

用于指定foreign key 约束的完整语法的一部分create table文档替换上面的短语和以下任何创建一个立即foreign key 约束

NOT DEFERRABLE INITIALLY DEFERRED -- 直接的foreign key 约束 NOT DEFERRABLE INITIALLY IMMEDIATE -- 直接的foreign key 约束 NOT DEFERRABLE -- 直接的foreign key 约束 DEFERRABLE INITIALLY IMMEDIATE -- 直接的foreign key 约束 DEFERRABLE -- 直接的foreign key 约束

下面例子举例说明如何使用延迟的效果foreign key 约束引用

-- 数据库模式两张表中.文本是左对齐的空 create table artist( artistID INTEGER PRIMARY KEY,trackartist IntegeR REFERENCES artist(artistID )DEFERRABLE INITIALLY DEFERRED ); sqlite3 > -- 如果使用外部键约束,这INSERT sqlite3 > -- 产生错误(自为该数据集在表艺术家具有 sqlite3 > -- artistID=5)但由于约束是推迟,并有一个名 sqlite3 > -- 打开事务,不会发生错误. sqlite3 > BEGIN; sqlite3 > INSERT INTO 跟踪VALUES(1,''white 圣诞节'',5) ; sqlite3 > -- 以下COMMIT 失败,作为数据库是在状态 sqlite3 > -- 不满足该延迟的foreign key 约束" sqlite3 > -- 事务保持打开状态. sqlite3 > COMMIT; sql 错误: foreign key 约束失败 sqlite3 > --,再将该艺人之后表artistID=5, sqlite3 > -- 延迟的foreign key 约束是osemailimmediately因此,可能 sqlite3 > -- 若要提交事务,没有出错 sqlite3 > INSERT INTO 艺术家VALUES(5,''bing crosby '') ; sqlite3 > COMMIT;

一个嵌套保存点在数据库正在一个事务,并可以RELEASEd 状态下,不满足一个延迟的foreign key 约束打开一个事务driveRMANager.setlogstream (一个non-nested 保存点当这些文件已经当前打开的transaction)在其他手形是作为COMMIT -将受到的限制也在数据库正在尝试RELEASE 但这样的状态将会失败

如果一个COMMIT 语句(或RELEASE 一个事务SAVEPOint) 失败,原因是该数据库目前在违反了延迟foreign key 约束和当前有嵌套savepoints,嵌套savepoints 仍保持打开.

43ON deletE 和ON updatE 操作

外键ON deletE 和ON updatE 用于配置点? 工? 具条款是从父表中删除行时(ON Delete)现有的行或修改的父键值(ON updatE)单个foreign key 约束可能有不同的操作配置为ON deletE 和ON updatE外键的操作类似"触发器"的方法有多种

在ON deletE 和ON updatE @R_262_4901@据库中的每个外键相关联的操作是"NO ACTION ""REStriCT ""SET NulL ""SET DEFAulT "或"CASCADE "如果动作未显式指定度量值,则默认为"NO ACTION "

  • NO ACTION: 配置"NO ACTION "的意思是: 当父键被修改或删除从数据库中删除.则不需要特殊的操作.

  • REStriCT: "REStriCT "动作的非零表示应用程序被删除(ON deletE REStriCT) 或修改(对于ON updatE REStriCT) parent key 时存在一个或多个子按键映射到它REStriCT"操作的效果之间的差异和普通外键约束强制进行处理动作的REStriCT 会发生这种情况的字段将更新-不能在当前语句是等价的.以直接的约束或末尾的当前事务将某个已推迟约束即使在外部键约束(它是附加到打印报表配置一个REStriCT 操作都会导致sqlite 返回一个错误立即如果将parent key 带有相关子键被删除或修改

  • SET NulL配置操作: 如果"SET NulL ",.当一个父键被删除(ON deletE SET NulL) 或修改(对于ON updatE SET NulL),子键的列在子表中所有的行映射到父键都被设置为包含sql NulL 值.

  • SET DEFAulT: "SET DEFAulT "的操作类似于"SET NulL "除了下列子键列不是可包含表格默认值,而不是NulL请参阅create table可能会影响默认值是被分配给表中的列

  • CASCADE: "CASCADE "操作传播到订阅服务器上的"delete 或update 操作父键为每个依赖的子键为"ON deletE CASCADE ",这意味着每个操作在子表中的行被关联到已删除的父行也被删除为"ON updatE CASCADE "操作,这意味着该值存储在每个依赖的子键都被修改以满足新的父键的值

例如,添加一个"ON updatE CASCADE "子句添加到外键如下图所示增强了这些示例架构从节1可以允许用户更新artistID (父键的抗参照完整性)列而不外键约束:

-- 数据库模式 create table artist( artistID INTEGER PRIMARY KEY,trackartist IntegeR REFERENCES artist(artistID )ON updatE CASCADE ); sqlite > SELECT *FROM 艺术家; artistID artistname -------- ----------------- 1: marTin 2弗兰克sinatra sqlite > SELECT *FROM 跟踪; 曲目长度trackname trackartist ------- ----------------- ----------- 11 的amore 1 圣诞节12 蓝色1 13 2的方法 sqlite > -- artistID 行的更新为"dean marTin "的艺术家记录 sqlite > -- 通常,这将引发一个约束,这会成为孤立的两个 sqlite > -- 依赖记录在跟踪表但是,该ON updatE CASCADE 子句 sqlite > -- 附加到外键定义会导致更新"cascade " sqlite > -- 到子表,导致的foreign key 约束冲突. sqlite > updatE 艺术家SET artistID =100 WHERE artistname =''dean marTin '' ; sqlite > SELECT *FROM 艺术家; artistID artistname -------- ----------------- 2弗兰克sinatra 100 : marTin sqlite > SELECT *FROM 跟踪; 曲目长度trackname trackartist ------- ----------------- ----------- 11 的amore 100 圣诞节12 布鲁斯100 13 2的方法

配置一个ON updatE 或ON deletE 操作并不意味着需要将外部键约束不满足例如如果一个"ON deletE SET DEFAulT "配置的操作在父表,但没有行的默认值相对应的子键列删除一个父键依赖的子键存在仍然会导致时.将发生外键违反例如:

div class="codeblock c13" style="Font-family:宋体,trackartist IntegeR DEFAulT 0REFERENCES artist(artistID )ON deletE SET DEFAulT ); sqlite > SELECT *FROM 艺术家; artistID artistname -------- ----------------- 3sAMMy davis 日记 sqlite > SELECT *FROM 跟踪; 曲目长度trackname trackartist ------- ----------------- ----------- 14 mrbojangles 3 sqlite > 删除行-- 从父表中的子键 sqlite > -- dependent 值设置为列表值0但是,此 sqlite > -- 值无效需要与在父表中的任何行因此,139)">-- foreign key 约束,和一个引发了异常. sqlite > deletE FROM 艺术家WHERE artistname ='��AMMy davis breeze 5.1'' ; sql 错误: foreign key 约束失败 sqlite > -- 此时,值0中对应于父表的行和 sqlite > -- 因此deletE 语句也不违反外键约束 sqlite > :10pt; color:rgb(0,并且没有为下列值之一: sqlite > INSERT INTO 艺术家VALUES(0,''unkNown 艺术家'') ; sqlite > deletE FROM 艺术家WHERE artistname ='��AMMy davis breeze 5.1'' ; sqlite > SELECT *FROM 艺术家; artistID artistname -------- ----------------- 0未知专辑 sqlite > SELECT *FROM 跟踪; 曲目长度trackname trackartist ------- ----------------- ----------- 14 mrbojangles 0

大佬总结

以上是大佬教程为你收集整理的SQLite 外键支持全部内容,希望文章能够帮你解决SQLite 外键支持所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: