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行为不会执行
相关推荐
### 使用触发器实现SQLite的外键约束 #### 背景与问题介绍 在进行数码相框嵌入式开发的过程中,开发团队选择了SQLite作为数据库管理系统。然而,在编码过程中遇到了一个较为棘手的问题:SQLite默认情况下不支持...
5. **SQLite外键.htm**:这可能是一个关于SQLite外键约束的HTML文档。外键是关系数据库中保持数据完整性的重要机制,它确保了引用的完整性和一致性。SQLite支持外键,但默认情况下是禁用的,需要在创建数据库时明确...
System.Data.SQLite.dll默认开启外键约束重新编译版,文件版本1.0.85.0,官网源码,除了开启外键约束,未作任何修改,内含.net2.0、.net4.0的32bit和64bit的release,以及源码修改说明。
本文将详细讲解如何使用C#语言配合SQLite数据库进行这项工作,为其他语言和数据库的映射提供参考。 首先,我们需要了解什么是实体类。在面向对象编程中,实体类是对现实世界中具有特定属性和行为的对象的抽象。它们...
1. **数据库设计**:SQLite Expert允许用户通过拖放方式创建和编辑表格,设置字段类型、约束(主键、唯一、外键等)、默认值和自增属性。此外,还可以创建和管理索引,优化查询性能。 2. **SQL编辑与调试**:内置的...
20. SQLITE_CONSTRAINT (19): 由于约束冲突(如主键、外键约束)导致操作失败。 21. SQLITE_MISMATCH (20): 数据类型不匹配,例如在插入数据时类型不符。 22. SQLITE_MISUSE (21): 对SQLite库的误用,可能是API调用...
你可以新建表,设置字段类型、长度、约束等属性,并轻松调整表之间的关系,如外键。 3. **数据操作**:该工具提供了一套完整的数据操作工具,包括添加、编辑、删除记录,以及批量导入和导出数据。这对于数据的录入...
4. **数据库设计**:可以设计和修改表结构,包括添加、删除或修改字段,设置主键、外键等关系。 5. **备份与导入导出**:支持数据库的备份和恢复,以及将数据导入和导出到CSV、XML、JSON等多种格式。 6. **图表和...
2. **数据库结构**:SQL Server与SQLite的表结构可能存在差异,例如字段类型、主键约束、外键约束等。工具需要处理这些差异,确保转换后的SQLite数据库能正确反映原始SQL Server的结构。 3. **数据类型映射**:SQL ...
它提供了高级选项,如表、列、索引和外键的可视化编辑。它还为导入和导出数据提供了多种工具。用户可以轻松地从 CSV 和 ADO 文件等来源导入数据,也可以将数据导出为 Excel 和 SQL 脚本等格式。通过拖放操作,SQLite...
这包括处理主键、外键、索引和其他约束。 总结来说,将PostgreSQL数据导入SQLite涉及多个步骤,包括备份、转换和导入。通过使用专门的工具如"Postgres2Sqlite",可以简化这个过程,特别是当需要频繁进行数据迁移或...
4. **索引和约束**:在MySQL中创建索引和外键约束可能需要额外的语法调整。 5. **性能优化**:MySQL提供多种性能优化策略,包括存储引擎的选择(如InnoDB),索引设计,查询优化等。 6. **安全考虑**:在迁移过程...
- 数据库设计:用户可以创建新表、修改表结构,定义主键、外键、索引等数据库元素。 - 图形化查询构建器:对于不熟悉SQL的用户,可以使用图形化工具构建查询,简化操作过程。 2. **安装与使用**: - 下载安装:...
2. **表管理**:创建、修改和删除数据库表,包括定义字段类型、主键、外键、索引等。还可以导入和导出数据,支持多种数据格式如CSV、XML、Excel等。 3. **查询构建器**:提供可视化查询构建工具,通过拖放字段和...
SQLite支持外键,这允许在不同表之间建立关系,实现数据的引用完整性。例如,创建一个`grades`表,其中`student_id`是`students`表的外键: ```sql CREATE TABLE grades ( id INTEGER PRIMARY KEY, student_id ...
这包括创建、修改和删除表格,定义字段类型,设置主键和外键等。 3. **查询构建器**:SQLite Database Browser 包含一个可视化的SQL查询构建器,帮助用户生成复杂的SELECT、INSERT、UPDATE和DELETE语句,无需手动...
表列,索引,外键,触发器,独特和检查约束的可视化编辑器。 任何复杂的表,而不会丢失数据重组。 任何重组操作被包裹在一个嵌套事务回滚,如果发生任何错误更改应用时。 导入和导出数据 从ADO数据源,CSV...
1. 数据库设计:你可以通过拖放操作创建和修改表结构,设置字段类型、约束(如主键、外键、唯一性约束)以及索引。 2. 数据浏览和编辑:直观的表格视图让你可以轻松浏览数据库中的数据,支持添加、修改和删除记录,...
也能设置表的主键、外键等约束,保证数据的完整性和一致性。 10. **存储过程与触发器**:虽然SQLite本身不直接支持存储过程,但可以通过自定义函数和触发器实现类似功能,SqliteClient也提供了相应的接口。 通过...
表列,索引,外键,触发器,独特和检查约束的可视化编辑器。 任何复杂的表,而不会丢失数据重组。 任何重组操作被包裹在一个嵌套事务回滚,如果发生任何错误更改应用时。 导入和导出数据 从ADO数据源,CSV文件...