44.md 7.6 KB
Newer Older
W
wizardforcel 已提交
1 2 3 4 5 6
# SQLite 约束

> 原文: [http://zetcode.com/db/sqlite/constraints/](http://zetcode.com/db/sqlite/constraints/)

在 SQLite 教程的这一部分中,我们将处理约束。

W
wizardforcel 已提交
7
约束 被放置在列上。 它们限制了可以插入表中的数据。
W
wizardforcel 已提交
8 9 10 11 12 13 14 15 16 17

在 SQLite 中,我们具有以下约束:

*   非空
*   独特
*   首要的关键
*   外键
*   校验
*   默认

W
wizardforcel 已提交
18
## SQLite `NOT NULL`约束
W
wizardforcel 已提交
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

具有`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`

W
wizardforcel 已提交
39
## SQLite `UNIQUE`约束
W
wizardforcel 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189

`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 版,并且必须设置外键的编译指示。

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

```

删除作者也会删除他的书。

W
wizardforcel 已提交
190
## SQLite `CHECK`约束
W
wizardforcel 已提交
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237

`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`约束将默认值插入到列中。

```
sqlite> CREATE TABLE Hotels(Id INTEGER PRIMARY KEY, Name TEXT, 
   ...> City TEXT DEFAULT 'not available');

```

为了演示`DEFAULT`约束,我们创建了`Hotels`表。 `City`列具有默认的“不可用”值。

```
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 将默认值(“不可用”文本)放在此处。

在 SQLite 教程的这一部分中,我们介绍了 SQLite 数据库支持的约束。