SQLite 外键支持

来源:互联网 发布:php javascript 传值 编辑:程序博客网 时间:2024/05/21 06:38
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 用于创建foreign key 约束的语法可以找到此文档的一部分CREATE TABLE 语句.

1简介foreign key 约束

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

CREATE TABLE artist( artistid INTEGER PRIMARY KEY,  artistname TEXT );CREATE TABLE track( 曲目长度INTEGER,  trackname TEXT,  trackartist INTEGER -- 必须映射到一个艺术家artistid!);

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

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

CREATE TABLE track( 曲目长度INTEGER,  trackname TEXT,  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 蓝色113 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, 两者都不SQLITE_OMIT_FOREIGN_KEY 或SQLITE_OMIT_TRIGGER 定义如果SQLITE_OMIT_TRIGGER 但SQLITE_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 ;0sqlite > PRAGMA foreign_keys =ON; sqlite > PRAGMA foreign_keys ;1sqlite > PRAGMA foreign_keys =OFF; sqlite > PRAGMA foreign_keys ;0

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

不能启用或禁用检查约束试试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 是一个错误, 因为即使父键列具有唯一的索引.索引使用不同的比较顺序表child6 和child7 是否不正确, 因为在同时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, y, 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 约束可能是:

CREATE TABLE artist( artistid INTEGER PRIMARY KEY,  artistname TEXT );CREATE TABLE track( 曲目长度INTEGER,  trackname TEXT,  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,  albumname TEXT,  albumcover BINARY,  PRIMARY KEY(albumartist,  albumname ));CREATE TABLE song( songid INTEGER,  songartist TEXT,  songalbum TEXT,  songname TEXT,  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 /ROLLBACK block) 事务, 然后隐式一旦完成执行该语句在这种情况下推迟约束即时相同约束

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

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,  artistname TEXT );CREATE TABLE track( 曲目长度INTEGER,  trackname TEXT,  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 SQLite 数据库中的每个外键相关联的操作是"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,  artistname TEXT );CREATE TABLE track( 曲目长度INTEGER,  trackname TEXT,  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 蓝色113 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 "配置的操作在父表, 但没有行的默认值相对应的子键列删除一个父键依赖的子键存在仍然会导致时.将发生外键违反例如:

-- 数据库模式CREATE TABLE artist( artistid INTEGER PRIMARY KEY,  artistname TEXT );CREATE TABLE track( 曲目长度INTEGER,  trackname TEXT,  trackartist INTEGER DEFAULT 0REFERENCES artist(artistid )ON DELETE SET DEFAULT );sqlite > SELECT *FROM 艺术家;artistid artistname -------- ----------------- 3sammy davis 日记sqlite > SELECT *FROM 跟踪;曲目长度trackname trackartist ------- ----------------- ----------- 14 mrbojangles 3sqlite > 删除行-- 从父表中的子键sqlite > -- dependent 值设置为列表值0但是, 此sqlite > -- 值无效需要与在父表中的任何行因此, sqlite > -- foreign key 约束, 和一个引发了异常.sqlite > DELETE FROM 艺术家WHERE artistname ='��ammy davis breeze 5.1'' ;SQL 错误: foreign key 约束失败sqlite > -- 此时, 值0中对应于父表的行和sqlite > -- 因此DELETE 语句也不违反外键约束sqlite > -- , 并且没有为下列值之一: 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 触发器将有一个"ON DELETE SET DEFAULT "中的操作演示了在以上示例中是相似的效果要以下AFTER DELETE 触发器:

CREATE TRIGGER on_delete_set_default AFTER DELETE ON 艺术家BEGIN UPDATE 子SET trackartist =0WHERE trackartist =旧artistid;END; 

当行中的父表的外键约束已被删除, 或者在将这些值存储在父键列或列被修改, 逻辑顺序事件的语法包含以下成分:

  1. 执行相应的BEFORE 触发程序,
  2. 检查本地(非foreign key )约束.
  3. 更新或删除这一行在父表.
  4. 执行任何所需的外键操作,
  5. 执行相应的AFTER 触发程序.

ON 之间有一个重要的区别需要注意UPDATE 外键操作和SQL 触发器一个ON 仅采取行动UPDATE 如果父键的值被修改, 这样新的父键的值不等于旧例如:

-- 数据库模式CREATE TABLE parent(x PRIMARY KEY); CREATE TABLE child(y REFERENCES 父ON UPDATE SET NULL); sqlite > SELECT *FROM 父;x---- 密钥sqlite > SELECT *FROM 子;y---- 密钥sqlite > -- 因为下列UPDATE 语句并不真正修改sqlite > -- 父键值越大, ON UPDATE 操作未执行, sqlite > -- 子键值未设置为NULL. sqlite > UPDATE 父SET x=''key '' ;sqlite > SELECT IFNULL(y,  FROM 子''null ");y---- 密钥sqlite > -- 此时间, 由于在UPDATE 语句并修改的父键sqlite > -- 值越大, ON UPDATE 设置并将执行指定的子操作sqlite > -- 若要NULL. sqlite > UPDATE 父SET x=''key2 '' ;sqlite > SELECT IFNULL(y,  FROM 子''null ");y---- null 

5CREATE, ALTER 和DROP TABLE 命令

本节描述了方式CREATE TABLE , ALTER TABLE 和DROP TABLE SQLite 的外键交互的命令

一个CREATE TABLE 将命令的作用相同foreign key 约束被启用父键定义时检查的foreign key 约束没有创建一个表服务器名无效停止用户从创建外部键定义, 该定义引用了一个不存在的父表不存在到父键列不存在或不让绑定由PRIMARY KEY 或UNIQUE 约束

"ALTER TABLE 在两个单独命令的使用方式有所不同如果启用foreign key 约束时:

  • 不能使用"ALTER TABLE ...ADD COLUMN "语法来添加一个列, 它包含REFERENCES 子句中, 除非该列必须为NULL. 默认值的新尝试这样做返回一个错误.

  • 如果一个"ALTER TABLE ...RENAME TO "命令用于删除重命名一个表, 该值是父表中有一个或多个foreign key 约束, delobj 系统变量可控制foreign key 约束改为从父表中引用它的新名称的列表.子CREATE TABLE 语句或语句存储在sqlite_master 表被修改以反映新的父表的名称

如果启用了foreign key 约束准备就绪, 时DROP TABLE 命令执行显式的DELETE 删除该表中的所有行, 然后再删除它隐式DELETE 不会导致任何SQL 用于激发触发器, 但需要调用外键或约束违规行为如果直接的外键违反约束, DROP TABLE 语句将失败并不会删除该表如果违反延迟foreign key 约束然后是报告了一个错误当用户试图提交该事务如果该点处的外键违反约束仍然存在任何"foreign 密钥不匹配"作为隐式DELETE 的一部分时遇到错误将被忽略

使用这些增强ALTER TABLE 和DROP TABLE 命令, 以确保它们不能用于创建一个包含外键违反被启用, 至少在foreign key 约束有一点例外以此规则尽管如果父键不为PRIMARY KEY 或UNIQUE 约束的一部分创建的父表定义但表单还包含一个UNIQUE 方正索引创建约束使用CREATE INDEX 命令, 则您将子表可能不导致填充一个"foreign 密钥不匹配"的错误如果UNIQUE 索引是数据库中: schema , 然后父表本身的查询时, 将不会报告了错误例如, 在状态可能是您的数据库子表的"foreign key 约束包含行没有引用任何父表中的行数这种情况下, 可以避免如果所有 父键在数据库中受PRIMARY 的架构是KEY 或UNIQUE 约束的父表定义, 而不能通过外部UNIQUE 索引.

的属性DROP TABLE 和ALTER TABLE 命令.当multiline 如果外键被启用如果用户将认为它们自动配置过程中, 则回避措施是使用PRAGMA foreign_keys 要执行DROP 之前禁用foreign key 约束或ALTER TABLE 命令当然, 在foreign key 约束被禁用, 停止用户和asset foreign key 约束由此创建内部数据库不一致

6限制和不支持的功能

本节列出了几个限制和.除非中没有提到的功能.

  1. 没有其他可用的MATCH 子句.根据SQL92, MATCH 子句的select 语句可能附加到外键定义如果要修改在地图上显示子键值的NULL 的方式处理如果"MATCH SIMPLE "被指定然后, 创建子键在清单中不是必需的, 与每个层相对应要对父表的任何行如果一个或多个子键值为NULL如果"MATCH FULL "被指定然后是NULL 如果任何子键值在"父表中没有相应的行是必需的但所有子键值必须NULL最后如果外键约束已被声明为"MATCH PARTIAL "和子键值之一是NULL必须存在至少有一个行在父表的non-NULL 子键值匹配的父键值

    SQLite 解析MATCH 子句(ie未报告语法错误如果指定one) , 但不强制在SQLite 获取的所有foreign key 约束如果MATCH 中指定了SIMPLE

  2. 在文件系统"%2$s"中切换约束之间的延迟和即时模式.许多系统允许用户之间切换各个foreign key 约束延迟和即时模式运行时(例如使用oracle "SET CONSTRAINT "command)SQLite 不支持这个在SQLite, foreign key 约束为永久标记为延迟或立即创建后,

  3. 外键操作.递归限制"SQLITE_MAX_TRIGGER_DEPTH 和SQLITE_LIMIT_TRIGGER_DEPTH 触发程序的设置决定了所允许的深度递归出于这些限制, 外键操作程序都被认为是触发器"PRAGMA recursive_triggers 设置不会不影响该操作的外部键操作不能禁用递归外键操作

0 0