SQLite 约束
最后修改于 2020 年 7 月 6 日
在本节 SQLite 教程中,我们将介绍约束。
约束 放置在列上。它们限制了可以插入到表中的数据。
在 SQLite 中,我们有以下约束
- NOT NULL(非空)
- UNIQUE
- PRIMARY KEY(主键)
- FOREIGN KEY(外键)
- CHECK(检查)
- DEFAULT(默认)
SQLite NOT NULL 约束
具有 NOT NULL
约束的列不能有 NULL
值。
sqlite> CREATE TABLE People(Id INTEGER, LastName TEXT NOT NULL, ...> FirstName TEXT NOT NULL, City TEXT);
我们创建了两个带有 NOT NULL
约束的列。
sqlite> INSERT INTO People VALUES(1, 'Hanks', 'Robert', 'New York'); sqlite> INSERT INTO People VALUES(2, NULL, 'Marianne', 'Chicago'); Error: People.LastName may not be NULL
第一个 INSERT
语句成功,而第二个失败。错误提示 LastName
列不能为 NULL
。
SQLite UNIQUE 约束
UNIQUE
约束确保所有数据在列中是唯一的。
sqlite> CREATE TABLE Brands(Id INTEGER, BrandName TEXT UNIQUE);
在这里,我们创建一个名为 Brands
的表。BrandName
列被设置为 UNIQUE
。不能有两个品牌具有相同的名称。
sqlite> INSERT INTO Brands VALUES(1, 'Coca Cola'); sqlite> INSERT INTO Brands VALUES(2, 'Pepsi'); sqlite> INSERT INTO Brands VALUES(3, 'Pepsi'); Error: column BrandName is not unique
我们得到一个错误“列 BrandName 不是唯一的”。只能有一个百事品牌。
请注意,PRIMARY KEY
约束自动在其上定义了一个 UNIQUE
约束。
SQLite 主键约束
PRIMARY KEY
约束唯一地标识数据库表中的每个记录。可以有更多 UNIQUE
列,但表中只能有一个主键。主键在设计数据库表时非常重要。主键是唯一的 ID。我们使用它们来引用表行。当在表之间创建关系时,主键成为其他表中的外键。由于一个“长期存在的编码疏忽”,主键在 SQLite 中可以为 NULL
。其他数据库则不然。
sqlite> DROP TABLE Brands; sqlite> CREATE TABLE Brands(Id INTEGER PRIMARY KEY, BrandName TEXT);
Brands
表的 Id
列成为 PRIMARY KEY
。
sqlite> INSERT INTO Brands(BrandName) VALUES('Coca Cola'); sqlite> INSERT INTO Brands(BrandName) VALUES('Pepsi'); sqlite> INSERT INTO Brands(BrandName) VALUES('Sun'); sqlite> INSERT INTO Brands(BrandName) VALUES('Oracle'); sqlite> SELECT * FROM Brands; Id BrandName ---------- ---------- 1 Coca Cola 2 Pepsi 3 Sun 4 Oracle
在 SQLite 中,如果一列是 INTEGER
并且是 PRIMARY KEY
,它也会自动递增。
SQLite 外键约束
一个表中的 FOREIGN KEY
指向另一个表中的 PRIMARY KEY
。它是两个表之间的引用约束。外键标识一个(引用)表中引用另一个(被引用)表中一列或一组列的列或一组列。
SQLite 文档将引用的表称为父表,将引用表称为子表。父键是父表中外键约束所引用的列或一组列。这通常(但不总是)是父表的主键。子键是子表中受外键约束约束并持有 REFERENCES
子句的列或一组列。
我们使用两个表来演示此约束:Authors
和 Books
。
-- SQL for the Authors & Books tables BEGIN TRANSACTION; DROP TABLE IF EXISTS Books; DROP TABLE IF EXISTS Authors; CREATE TABLE Authors(AuthorId INTEGER PRIMARY KEY, Name TEXT); INSERT INTO Authors VALUES(1, 'Jane Austen'); INSERT INTO Authors VALUES(2, 'Leo Tolstoy'); INSERT INTO Authors VALUES(3, 'Joseph Heller'); INSERT INTO Authors VALUES(4, 'Charles Dickens'); CREATE TABLE Books(BookId INTEGER PRIMARY KEY, Title TEXT, AuthorId INTEGER, FOREIGN KEY(AuthorId) REFERENCES Authors(AuthorId)); INSERT INTO Books VALUES(1,'Emma',1); INSERT INTO Books VALUES(2,'War and Peace',2); INSERT INTO Books VALUES(3,'Catch XII',3); INSERT INTO Books VALUES(4,'David Copperfield',4); INSERT INTO Books VALUES(5,'Good as Gold',3); INSERT INTO Books VALUES(6,'Anna Karenia',2); COMMIT;
这是用于创建 Books
和 Authors
表的 SQL。Books
表的 AuthorId
列具有外键约束。它引用了 Authors
表的主键。
在 SQLite 中,默认情况下不强制执行外键。要强制执行外键,库必须使用正确的标志编译,它必须至少是版本 3.6.19,并且必须设置外键的 pragma 键。
sqlite> PRAGMA foreign_keys=1;
使用 PRAGMA
语句强制执行外键。
sqlite> DELETE FROM Authors WHERE AuthorId=1; Error: foreign key constraint failed
尝试删除仍在 Books
表中拥有书籍的作者会导致错误。该作者未被删除。
sqlite> DELETE FROM Books WHERE AuthorId=1; sqlite> DELETE FROM Authors WHERE AuthorId=1; sqlite> SELECT * FROM Authors; AuthorId Name --------------- ------------------ 2 Leo Tolstoy 3 Joseph Heller 4 Charles Dickens
为了删除作者,我们必须删除他在 Books
表中的书籍。
可以定义当必须强制执行外部约束时将要采取的操作。默认操作是 RESTRICT
,这意味着不允许删除或更新。
CREATE TABLE Books(BookId INTEGER PRIMARY KEY, Title TEXT, AuthorId INTEGER, FOREIGN KEY(AuthorId) REFERENCES Authors(AuthorId) ON DELETE CASCADE);
我们修改了 Books
表的模式,其中我们添加了 ON DELETE CASCADE
操作。此操作意味着操作从父表 (Authors
) 传播到子表 (Books
)。
sqlite> SELECT Name, Title FROM Authors NATURAL JOIN Books; Name Title --------------- ------------------ Jane Austen Emma Leo Tolstoy War and Peace Joseph Heller Catch XII Charles Dickens David Copperfield Joseph Heller Good as Gold Leo Tolstoy Anna Karenia sqlite> DELETE FROM Authors WHERE AuthorId=2; sqlite> SELECT Name, Title FROM Authors NATURAL JOIN Books; Name Title --------------- ------------------ Jane Austen Emma Joseph Heller Catch XII Charles Dickens David Copperfield Joseph Heller Good as Gold
删除作者也会删除他的书籍。
SQLite CHECK 约束
CHECK
子句对关系数据库的数据施加有效性约束。在将数据添加到相关列或更新数据时,将执行检查。
sqlite> .schema Orders CREATE TABLE Orders(Id INTEGER PRIMARY KEY, OrderPrice INTEGER CHECK(OrderPrice>0), Customer TEXT);
我们看一下 Orders 表的定义。我们看到对 OrderPrice
列施加了 CHECK
约束。当然,订单的价格必须是一个正值。
sqlite> INSERT INTO Orders(OrderPrice, Customer) VALUES(-10, 'Johnson'); Error: constraint failed
如果我们尝试插入一个无效值,我们会收到一个错误,提示“约束失败”。
SQLite DEFAULT 约束
如果没有任何值可用,DEFAULT
约束会在列中插入一个默认值。
sqlite> CREATE TABLE Hotels(Id INTEGER PRIMARY KEY, Name TEXT, ...> City TEXT DEFAULT 'not available');
为了演示 DEFAULT
约束,我们创建了一个 Hotels
表。City
列有一个默认的“not available”(不可用)值。
sqlite> INSERT INTO Hotels(Name, City) VALUES('Kyjev', 'Bratislava'); sqlite> INSERT INTO Hotels(Name) VALUES('Slovan'); sqlite> .width 3 8 17 sqlite> SELECT * FROM Hotels; Id Name City --- -------- ----------------- 1 Kyjev Bratislava 2 Slovan not available
在第一条语句中,我们同时提供了酒店名称和城市名称。在第二条语句中,我们只提供了酒店名称。SQLite 在那里放置了默认值,即“not available”文本。
在本节 SQLite 教程中,我们介绍了 SQLite 数据库支持的约束。