# MySQL 约束

> 原文： [http://zetcode.com/databases/mysqltutorial/constraints/](http://zetcode.com/databases/mysqltutorial/constraints/)

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

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

我们有以下限制：

*   非空
*   唯一
*   主键
*   外键
*   枚举
*   组

其他数据库也具有`CHECK`约束，该约束为有效数据设置了条件。 MySQL 解析了这个约束，但是没有强制执行。

### 非空约束

具有`NOT NULL`约束的列不能具有`NULL`值。

```sql
mysql> CREATE TABLE People(Id INTEGER, LastName TEXT NOT NULL,
    ->                     FirstName TEXT NOT NULL, City VARCHAR(55));
Query OK, 0 rows affected (0.07 sec)

```

我们创建两个具有`NOT NULL`约束的列。

```sql
mysql> INSERT INTO People VALUES(1, 'Hanks', 'Robert', 'New York');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO People VALUES(1, NULL, 'Marianne', 'Chicago');
ERROR 1048 (23000): Column 'LastName' cannot be null

```

第一个`SELECT`语句执行成功，第二个失败。 SQL 错误说，`LastName`列不能为空。

### 唯一约束

`UNIQUE`约束确保所有数据在列中都是唯一的。

```sql
mysql> CREATE TABLE Brands(Id INTEGER, BrandName VARCHAR(30) UNIQUE);
Query OK, 0 rows affected (0.08 sec)

```

在这里，我们创建一个表`Brands`。 `BrandName`列设置为`UNIQUE`。 不能有两个名称相同的品牌。

```sql
mysql> INSERT INTO Brands VALUES(1, 'Coca Cola');
Query OK, 1 row affected (0.03 sec)

mysql> INSERT INTO Brands VALUES(2, 'Pepsi');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO Brands VALUES(3, 'Pepsi');
ERROR 1062 (23000): Duplicate entry 'Pepsi' for key 'BrandName'

```

对于键“`BrandName`”，我们收到一个 SQL 错误，重复项“`Pepsi`”。 只能有一个百事可乐品牌。

注意，`PRIMARY KEY`约束自动在其上定义了`UNIQUE`约束。

### 主键

`PRIMARY KEY`约束唯一地标识数据库表中的每个记录。 这是唯一键的特例。 主键不能为`NULL`，唯一键可以为。 可以有更多`UNIQUE`列，但是表中只有一个主键。 在设计数据库表时，主键很重要。 主键是唯一的 ID。 我们使用它们来引用表行。 在表之间创建关系时，主键成为其他表中的外键。

```sql
mysql> DROP TABLE Brands;
mysql> CREATE TABLE Brands(Id INTEGER PRIMARY KEY, BrandName VARCHAR(30) UNIQUE);

```

`Brands`表的`Id`列成为主键。

```sql
mysql> DESCRIBE Brands;
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| Id        | int(11)     | NO   | PRI | NULL    |       |
| BrandName | varchar(30) | YES  | UNI | NULL    |       |
+-----------+-------------+------+-----+---------+-------+

```

`DESCRIBE`语句显示有关表中各列的信息。 我们可以看到`Id`列定义了`PRIMARY KEY`，`BrandName`设置了`UNIQUE`约束。 在处理特定表时，主键用于唯一标识表中的行。 唯一键强制列中的所有数据都不重复。

### 外键

一个表中的`FOREIGN KEY`指向另一表中的`PRIMARY KEY`。 它是两个表之间的引用约束。 外键标识一个（引用）表中的一列或一组列，该列或表引用另一（引用）表中的一列或一组列。

我们将在两个表上显示此约束：`Authors`和`Books`。

```sql
mysql> CREATE TABLE Authors(AuthorId INTEGER PRIMARY KEY, Name VARCHAR(70))
    -> type=InnoDB;

```

在这里，我们创建`Authors`表。 在 MySQL 中，引用表和被引用表必须是 InnoDB 或 BDB 存储引擎。 在 MyISAM 存储引擎中，将解析外键，但不会强制使用外键。

```sql
mysql> CREATE TABLE Books(BookId INTEGER PRIMARY KEY, Title VARCHAR(50),
    -> AuthorId INTEGER, FOREIGN KEY(AuthorId) REFERENCES Authors(AuthorId))
    -> type=InnoDB;

```

我们创建`Books`表。 在这里，我们有一个`AuthorId`列名，它用作外键。 它引用`Authors`表的主键。

在我们的示例中，外键强制执行意味着什么？ 我们无法使用`Authors`本书中没有的`AuthorId`在`Books`表中插入一行。

### `ENUM`约束

`ENUM`是一个字符串对象，其值是从允许值列表中选择的。 在创建表时，它们在列规范中显式枚举。

```sql
mysql> CREATE TABLE Shops(Id INTEGER, Name VARCHAR(55), 
    -> Quality ENUM('High', 'Average', 'Low'));

```

我们有一个`Shops`表。 该表具有定义的`Id`，`Name`和`Quality`列。 `Quality`列是`ENUM`。 它允许具有三个指定值之一：`High`，`Average`或`Low`。

```sql
mysql> INSERT INTO Shops VALUES(1, 'Boneys', 'High');
mysql> INSERT INTO Shops VALUES(2, 'AC River', 'Average');
mysql> INSERT INTO Shops VALUES(3, 'AT 34', '**');
mysql> SELECT * FROM Shops;
+------+----------+---------+
| Id   | Name     | Quality |
+------+----------+---------+
|    1 | Boneys   | High    |
|    2 | AC River | Average |
|    3 | AT 34    |         |
+------+----------+---------+

```

在前两个语句中，我们插入了两行。 在第三种情况下，该值在`ENUM`中不可用。 在这种情况下，将插入一个空字符串。

### `SET`约束

`SET`可以具有零个或多个值。 每个值都必须从允许值列表中选择。

```sql
mysql> CREATE TABLE Students(Id INTEGER, Name VARCHAR(55), 
    -> Certificates SET('A1', 'A2', 'B1', 'C1')); 

```

我们有一个`Students`表。 在此表中，我们有一个“证书”列。 每个学生可以拥有 0、1 个或多个这些证书。 这与`ENUM`约束不同，在`ENUM`约束中，允许值列表中只能有一个不同的值。

```sql
mysql> INSERT INTO Students VALUES(1, 'Paul', 'A1,B1');
mysql> INSERT INTO Students VALUES(2, 'Jane', 'A1,B1,A2');
mysql> INSERT INTO Students VALUES(3, 'Mark', 'A1,A2,D1,D2');
mysql> SELECT * FROM Students;
+------+------+--------------+
| Id   | Name | Certificates |
+------+------+--------------+
|    1 | Paul | A1,B1        |
|    2 | Jane | A1,A2,B1     |
|    3 | Mark | A1,A2        |
+------+------+--------------+

```

保罗有两个证书，珍妮有三个，马克有四个，但是只有两个被认可，因此只有前两个被写到了桌子上。 证书用逗号分隔。 不允许有空格。

在 MySQL 教程的这一部分中，我们介绍了 MySQL 支持的约束。