SQLite外键

SQLite外键(Foreign Key)支持

从SQLite 3.6.19 开始支持 外键约束. (Ubuntu 10.04 的SQLite版本是 3.6.22,  Debian 6.0 的SQLite版本是  3.7.0)

外键约束用来强制 两个表之间”存在”的关系. 比如, 考虑下面的SQL命令建立的schema

CREATE TABLE artist(
artistid INTEGER PRIMARY KEY,
artistname TEXT
);
CREATE TABLE track(
trackid INTEGER,
trackname TEXT,
trackartist INTEGER — 必须映射到一个 artist.artistid 记录
);
使用这个数据库的应用可以假定: 对于在track表里每一行, 都在artist表都存在一个对应的行.   不幸的是, 如果用户使用外部工具编辑数据库, 或者在应用程序中存在一个bug. 那么可能在track表中插入一行,而在artist表中没有相应的记录. 或者, 在artist表中删除某些行,  就会在track表里留下孤儿行(orphaned rows),  它们在artist表中剩下的记录找到任何对应的行.  这可能在以后会导致应用的功能出错. 或者至少让编写应用程序更复杂.

一个解决方法就是, 为数据库添加一个外键约束,在artist和track这两个表之间强制实施一个约束. 增加外键定义的track表的定义如下:
CREATE TABLE track(
trackid     INTEGER,
trackname   TEXT,
trackartist INTEGER,
FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);

这样,外键约束就由SQLite强制实施.  往 track表插入一行 在 artist表中没有对应的数据的记录的企图注定是要失败的,o(∩∩)o

如果在track表还存在依赖于artist中的某行的记录, 那么尝试从 artist表删除该行, 也会失败.

也就是说, 对于在track表中的每一行,,下面的表达式都是真:

trackartist IS NULL OR EXISTS(SELECT 1 FROM artist WHERE artistid=trackartist)

在SQLite中启用外键支持

1)为了在SQLite中使用外键约束, 编译sqlite库时, 不能使用 忽略 外键和触发器, 也就是 SQLITE_OMIT_FOREIGN_KEY 和 SQLITE_OMIT_TRIGGER不能被定义

2)必须在运行时打开, 因为  默认是关闭的

PRAGMA foreign_keys = ON;

要求和建议的数据库索引

通常, 外键约束的父键在父表里是主键. 如果它们不是主键, 那么父键栏 必须受一个UNIQUE约束 或者 有一个 UNIQUE 索引.

如果数据库schema还有外键错误, 就需要查看多个表才能找到错误. 数据表创建时不会检测这些错误,

这些错误会阻止应用程序 用SQL语句来修改子表或者父表的内容. 当内容被改变时,报告”DML errors”;当schema被改变时报告”DDL errors”

也就是说,错误地配置外键约束,要求检查子表和父表的是DML错误, 一般显示”foreign key mismatch” 或者 “no such table”

SELECT rowid FROM <child-table> WHERE <child-key> = :parent_key_value
如果这个SELECT返回数据, 那么SQLite就断定, 从父表删除某行, 将会违背外键约束,并返回错误. 如果父键的值被修改或者在父表插入新的一行,也会产生类似的查询.

如果这些查询没有使用索引, 它们将强迫对整个子表做线性 查找(scan), 这代价可太大了

在大多数实际系统中,  应该在子键这一栏建立索引. 子键的索引不必(并且是通常都不必) 有一个UNIQUE 索引(因为在子表中的多行对应于父表中的一行)

CREATE INDEX trackindex ON track(trackartist);
 

ON DELETE 和 ON UPDATE行为

外键的ON DELETE和 ON  UPDATE从句, 可以用来配置  当从父表中删除 某些行时发生的行为(ON DELETE).  或者 修改存在的行的父键的值, 发生的行为(ON UPDATE)

单个外键约束可以为ON DELETE和ON UPDATE配置不同的行为.   外键行为在很多时候类似于 触发器(trigger)

ON DELETE和ON UPDATE的行为是 NO ACTION,  RESTRICT, SET NULL,  SET DEFAULT 或者 CASCADE

如果没有明确指定星闻,那么默认就是NO ACTION

NO ACTION: 当父键被修改或者删除时, 没有特别的行为发生

RESTRICT:  存在一个或者多个子键对应于相应的父键时,  应用程序禁止删除(ON DELETE RESTRICT)或者修改(ON UPDATE RESTRICT) 父键

RESTRICT与普通的外键约束的区别是,  当字段(field)更新时, RESTRICT行为立即发生

SET NULL: 父键被删除(ON DELETE SET NULL) 或者修改 (ON UPDATE SET NULL)

SET DEFAULT: 类似于SET NULL

CASCADE: 将实施在父键上的删除或者更新操作,传播给与之关联的子键.

对于 ON DELETE CASCADE, 同被删除的父表中的行 相关联的子表中的每1行,也会被删除.

对于ON UPDATE CASCADE,  存储在子表中的每1行,对应的字段的值会被自动修改成同新的父键匹配

举例:

CREATE TABLE artist(

artistid    INTEGER PRIMARY KEY,

artistname  TEXT

);

CREATE TABLE track(

trackid     INTEGER,

trackname   TEXT,

trackartist INTEGER REFERENCES artist(artistid) ON UPDATE CASCADE

);

INSERT INTO artist VALUES(1, ‘Dean Martin’);

INSERT INTO artist VALUES(2, ‘Frank Sinatra’);

INSERT INTO track VALUES(14, ‘Mr. Bojangles’, 2);

INSERT INTO track VALUES(15, “That’s Amore”, 2);

INSERT INTO track VALUES(12, ‘Christmas Blues’, 1);

INSERT INTO track VALUES(13, ‘My Way’, 2);

sqlite> PRAGMA foreign_keys = ON;

(默认是关闭的, 要在运行时打开)

sqlite> SELECT * FROM artist;

1|Dean Martin

2|Frank Sinatra

sqlite> SELECT * FROM track;

14|Mr. Bojangles|2

15|That’s Amore|2

12|Christmas Blues|1

13|My Way|2

sqlite> UPDATE artist SET artistid = 999 WHERE artistname = ‘Dean Martin’;

(为 Dean Martin更改 artist表中的artistid栏目.

一般情况下, 这将 产生一个约束, 因为会让 track表中的 一条记录成为孤儿记录

但 对外键定义使用了ON UPDATE CASCADE从句后,  会把这个更新传给 子表, 从而让外键约束不被打破)

sqlite> SELECT * FROM artist;

2|Frank Sinatra

999|Dean Martin

sqlite> SELECT * FROM track;
14|Mr. Bojangles|2
15|That’s Amore|2
12|Christmas Blues|999
13|My Way|2
配置一个ON UPDATE或者ON DELETE行为并不意味着 外键约束 并不必要满足.
举例来说, 如果 配置了 ON DELETE SET DEFAULT 行为, 如果在父表中没有 与子表栏目中默认值 相对应 的 行记录, 当依赖的子键存在于子表中是, 删除父键, 会破坏外键.
举例:
sqlite> PRAGMA foreign_keys = ON;
CREATE TABLE artist(
artistid INTEGER PRIMARY KEY,
artistname TEXT
);
CREATE TABLE track(
trackid INTEGER,
trackname TEXT,
trackartist INTEGER DEFAULT 0 REFERENCES artist(artistid) ON DELETE SET DEFAULT
);
INSERT INTO artist VALUES(3, ‘Sammy Davis Jr.’);
INSERT INTO track VALUES(14, ‘Mr. Bojangles’, 3);
sqlite> DELETE FROM artist WHERE artistname = ‘Sammy Davis Jr.’;
Error: foreign key constraint failed
从父表中删除一行, 会引起子表中相关的子键被设置成整数0
然而, 这个值不对应与 附表中的任何一行数据. 所以,外键约束被打破, 就抛出了异常
sqlite> INSERT INTO artist VALUES(0, ‘Unknown Artist’);
往父表中添加一行, 其主键为0
这样删除记录就不会打破外键约束了
sqlite> DELETE FROM artist WHERE artistname = ‘Sammy Davis Jr.’;

sqlite> SELECT * FROM artist;
0|Unknown Artist
sqlite> SELECT * FROM track;
14|Mr. Bojangles|0
这写都很类似于 SQLite 触发器(triggers), ON DELETE SET DEFAULT行为, 在效果上, 同下面的 AFTER DELETE 触发器是类似的
CREATE TRIGGER on_delete_set_default AFTER DELETE ON artist BEGIN
UPDATE child SET trackartist = 0 WHERE trackartist = old.artistid;
END;
外键约束的父表中的某行被删除, 或者存储在父键中的值 被修改时: 时间的逻辑顺序是:
1. 执行在BEFORE 触发器程序
2. 检查本地(非外键)约束
3. 在父表中 更新或者删除行
4. 执行要求的外键行为
5. 执行 AFTER触发器 程序

在ON UPDATE外键行为 和 SQL 触发器之间一个重要区别就是, ON UPDATE 行为只有在 父键的值 被修改并且父键的值修改得跟原来不一样时,才执行.
如果下UPDATE SET 语句修改的值,跟原来一样, ON UPDATE行为不会执行

转载于:https://www.cnblogs.com/myoungho/archive/2010/11/07/1871041.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/475847.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

帝国cms搜索php分页,帝国cms V7.2自定义分页(列表分页,内容分页)样式步骤

【1】自己修改帝国cms默认的分页样式(css)&#xff0c;这样做的好处是你不用去改动帝国的核心文件&#xff0c;方便以后升级。【2】自己动手去修改帝国的分页(phpcss)&#xff0c;帝国的分页在e>class>下的t_functions.php这个文件里。列表页模板[!--show.page--]:分页导…

LeetCode 435. 无重叠区间(贪心/动态规划)

文章目录1. 题目2. 解题2.1 贪心2.2 动态规划1. 题目 给定一个区间的集合&#xff0c;找到需要移除区间的最小数量&#xff0c;使剩余区间互不重叠。 注意: 可以认为区间的终点总是大于它的起点。 区间 [1,2] 和 [2,3] 的边界相互“接触”&#xff0c;但没有相互重叠。 示例…

UDP广播包的研究

一直以来听的多了&#xff0c;什么UDP广播之类的&#xff0c;不过自己一直没有试验过&#xff0c;这次闲来无聊&#xff0c;于是测试了一下。网上说的其实并不是非常的正确&#xff0c;流传着不少的错误言论&#xff0c;这次自己动手测试了一下&#xff0c;没想到比我想象中的还…

php传递字符串给python,用PHP和Python生成短链接服务的字符串ID

假设你想做一个像微博短链接那样的短链接服务&#xff0c;短链接服务生成的URL都非常短例如: http://t.cn/E70Piib, 我们应该都能想到链接中的E70Piib对应的就是存储长链接地址的数据记录的ID&#xff0c;可是这个有大小写字母和数字构成的唯一ID是怎么生成的呢&#xff0c;刚学…

LeetCode 433. 最小基因变化(广度优先搜索)

1. 题目 一条基因序列由一个带有8个字符的字符串表示&#xff0c;其中每个字符都属于 “A”, “C”, “G”, "T"中的任意一个。 假设我们要调查一个基因序列的变化。一次基因变化意味着这个基因序列中的一个字符发生了变化。 例如&#xff0c;基因序列由"AAC…

JCP执行委员会新成员选举结果揭晓:Hologic未获通过

转载于:https://www.cnblogs.com/mixer/archive/2010/11/09/2448777.html

matlab fig生成exe,MATLAB GUI多个m文件和fig如何生成exe文件

&#xff0b;文件。命令的格式为&#xff1a;mcc[-option]fun[fun2...][mexfile1.....&#xff0b;文件。命令的格式为&#xff1a;mcc[-option]fun[fun2...][mexfile1.....function start_Callback(hObject, eventdata, handle...你的意思是&#xff1a;多个m文件导成一个吗&a…

Eclipse 编写代码自动提示设置

很多人不知道Eclipse如何开启代码助手的自动提示功能&#xff0c;只是使用Eclipse默认的输入了“.”之后才会出现提示。实际上可以输入任何字符的时候都可以给出提示。 设置如下: 打开 Eclipse -> Window -> Perferences&#xff0c;会打开个Perferences 的设置界面。 打…

LeetCode 436. 寻找右区间(二分查找)

1. 题目 给定一组区间&#xff0c;对于每一个区间 i&#xff0c;检查是否存在一个区间 j&#xff0c;它的起始点大于或等于区间 i 的终点&#xff0c;这可以称为 j 在 i 的“右侧”。 对于任何区间&#xff0c;你需要存储的满足条件的区间 j 的最小索引&#xff0c;这意味着区…

老鼠走迷宫php算法,C语言经典算法 - 老鼠走迷官(一)

C语言经典算法 - 老鼠走迷官(一)说明老鼠走迷宫是递回求解的基本题型&#xff0c;我们在二维阵列中使用2表示迷宫墙壁&#xff0c;使用1来表示老鼠的行走路径&#xff0c;试以程式求出由入口至出口的路径。解法老鼠的走法有上、左、下、右四个方向&#xff0c;在每前进一格之后…

LeetCode 491. 递增子序列(回溯+判重剪枝)

1. 题目 给定一个整型数组, 你的任务是找到所有该数组的递增子序列&#xff0c;递增子序列的长度至少是2。 示例: 输入: [4, 6, 7, 7] 输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]说明: 给定数组的长度不会超过15。 数组中的整数范…

[网络收集]Web.config配置文件详解

摘录自&#xff1a;http://hi.baidu.com/fanfanwuji/blog/item/a7fd8928d49a7ef098250a06.html 花了点时间整理了一下ASP.NET Web.config配置文件的基本使用方法。很适合新手参看&#xff0c;由于Web.config在使用很灵活&#xff0c;可以自定义一些节点。所以这里只介绍一些比较…

python怎么写方程条件,条件方程曲线拟合

在xmin处多项式的导数0的条件可以表示为一个简单的约束&#xff0c;这意味着变量p2&#xff0c;p3&#xff0c;和{}实际上并不独立。衍生条件是p2 2*p3*xmin 3*p4*xmin**2 0其中xmin是xdata的最小值。此外&#xff0c;xmin将在fit之前知道(如果不一定是在编写脚本时)&#x…

LeetCode 525. 连续数组(前缀和+哈希)

1. 题目 给定一个二进制数组, 找到含有相同数量的 0 和 1 的最长连续子数组&#xff08;的长度&#xff09;。 示例 1: 输入: [0,1] 输出: 2 说明: [0, 1] 是具有相同数量0和1的最长连续子数组。示例 2: 输入: [0,1,0] 输出: 2 说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的…

SQL Server常用的系统存储过程应用实例(转)

摘要&#xff1a;Sql Server自带的系统存储过程有许多&#xff0c;但大部分我们是不常用的。我在实践中根据自己的体会&#xff0c;总结整理了一些比较常用的&#xff0c;加上一些实例介绍给大家。本期介绍&#xff1a; l sp_attach_db l sp_attach_single_fil…

angular 权限 php,PHP,Angular,HTACCESS-仅允许来自源域的请求

我完成了我的角度项目。在我的项目中&#xff0c;我向PHP文件发送带有数据的POST请求&#xff0c;然后将结果返回给Angular。现在我只允许来自源域的请求&#xff0c;并拒绝来自任何域的请求。我尝试使用:header("Access-Control-Allow-Origin: example.com");但不管…

LeetCode 516. 最长回文子序列(动态规划)

1. 题目 给定一个字符串s&#xff0c;找到其中最长的回文子序列。可以假设s的最大长度为1000。 示例 1: 输入: "bbbab" 输出: 4 一个可能的最长回文子序列为 "bbbb"。示例 2: 输入: "cbbd" 输出: 2 一个可能的最长回文子序列为 "bb"…

点击图片,AJAX删除后台图片文件

点击页面上的图片&#xff0c;用jQuery的AJAX来删除后台真实的文件。包含了2个页面&#xff0c;一个是显示图片的页面&#xff0c;一个是传递文件名&#xff0c;然后删除真实图片的页面。具体的代码如下&#xff1a;ShowPics.htm:<!DOCTYPE html PUBLIC "-//W3C//DTD X…

granule size oracle,_ksmg_granule_size oracle内存分配粒度

_ksmg_granule_size oracle内存分配粒度_ksmg_granule_size:内存分配粒度大小oracle内存分配的最小单位&#xff0c;最终分配的内存数量都是这个参数的整数倍10g中这个参数的大小一般遵循如下原则&#xff1a;– sga_max_size < 1024M then _ksmg_granule_size 4M- sga_ma…

LeetCode 第 26 场双周赛(363/1971,前18.4%)

文章目录1. 比赛结果2. 题目1. LeetCode 5396. 连续字符 easy2. LeetCode 5397. 最简分数 medium3. LeetCode 5398. 统计二叉树中好节点的数目 medium4. LeetCode 5399. 数位成本和为目标值的最大数字 hard1. 比赛结果 做出来了 1、2、3 题&#xff0c;19分钟做出来3题&#x…