ZetCode

SQLite 约束

最后修改于 2020 年 7 月 6 日

在本节 SQLite 教程中,我们将介绍约束。

约束 放置在列上。它们限制了可以插入到表中的数据。

在 SQLite 中,我们有以下约束

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 子句的列或一组列。

我们使用两个表来演示此约束:AuthorsBooks

-- 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;

这是用于创建 BooksAuthors 表的 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 数据库支持的约束。