# 主键与唯一约束

URL: https://caijiao.org/postgresql/advanced/constraints/primary-unique
Source: docs/postgresql/advanced/constraints/primary-unique.md
Description: 介绍 PostgreSQL 中的主键与唯一约束，帮助开发者理解如何确保数据的唯一性和完整性，避免数据重复。

在 PostgreSQL 中，主键（Primary Key）和唯一约束（Unique Constraint）是用于确保数据完整性和唯一性的两种重要工具。它们帮助开发者确保数据库表中的数据没有重复并且每行数据都有唯一标识。

## 主键 (Primary Key)

主键是数据库表中用来唯一标识每一行数据的列或组合列。每个表只能有一个主键，主键约束自动为列或组合列创建索引，并确保数据的唯一性。

### 主键基本语法

创建表时，可以在列定义中指定主键：

```sql
CREATE TABLE users (
  user_id SERIAL PRIMARY KEY,
  username VARCHAR(100) NOT NULL,
  email VARCHAR(100) UNIQUE
);
````

在这个示例中，`user_id` 是主键，确保每个用户都有一个唯一的标识符。

### 主键的特性

* **唯一性**：主键列中的每个值都是唯一的。
* **非空性**：主键列中的每个值都不能为空。
* **自动索引**：PostgreSQL 会自动为主键列创建索引，以加速查询。

### 修改主键

如果你想修改主键，可以使用 `ALTER TABLE` 语句：

```sql
ALTER TABLE users
ADD CONSTRAINT users_pk PRIMARY KEY (user_id);
```

### 删除主键

如果你想删除主键约束，可以使用以下命令：

```sql
ALTER TABLE users
DROP CONSTRAINT users_pk;
```

## 唯一约束 (Unique Constraint)

唯一约束确保列中的所有值是唯一的。与主键不同，唯一约束允许列中有多个空值（NULL），而主键不允许有空值。

### 唯一约束基本语法

唯一约束可以在列定义中指定，也可以在表定义后添加：

```sql
CREATE TABLE users (
  user_id SERIAL PRIMARY KEY,
  username VARCHAR(100) UNIQUE,
  email VARCHAR(100) UNIQUE
);
```

在这个示例中，`username` 和 `email` 列都具有唯一约束，确保它们的值在表中是唯一的。

### 唯一约束的特性

* **唯一性**：唯一约束确保列中的每个值都是唯一的。
* **允许 NULL**：唯一约束允许列中的多个 NULL 值。
* **自动索引**：PostgreSQL 会自动为唯一约束列创建索引。

### 修改唯一约束

如果你需要修改唯一约束，可以使用 `ALTER TABLE`：

```sql
ALTER TABLE users
ADD CONSTRAINT unique_email UNIQUE (email);
```

### 删除唯一约束

如果你需要删除唯一约束，可以使用以下命令：

```sql
ALTER TABLE users
DROP CONSTRAINT unique_email;
```

## 主键与唯一约束的区别

| 特性       | 主键 (Primary Key) | 唯一约束 (Unique Constraint) |
| -------- | ---------------- | ------------------------ |
| **唯一性**  | 保证唯一性            | 保证唯一性                    |
| **空值**   | 不允许空值 (NULL)     | 允许多个空值 (NULL)            |
| **数量限制** | 每个表只能有一个主键       | 一个表可以有多个唯一约束             |
| **自动索引** | 自动创建索引           | 自动创建索引                   |

## 联合主键与唯一约束

可以使用多个列来组合主键或唯一约束，确保这些列的组合是唯一的。

### 联合主键

```sql
CREATE TABLE orders (
  order_id SERIAL,
  product_id INT,
  PRIMARY KEY (order_id, product_id)
);
```

在这个例子中，`order_id` 和 `product_id` 的组合列是主键，确保每个产品在每个订单中只有一个条目。

### 联合唯一约束

```sql
CREATE TABLE orders (
  order_id SERIAL,
  product_id INT,
  UNIQUE (order_id, product_id)
);
```

在这个例子中，`order_id` 和 `product_id` 组合具有唯一约束，确保每个订单中的每个产品是唯一的。

## 小结

主键和唯一约束是 PostgreSQL 中保证数据唯一性和完整性的核心机制。主键列不仅能确保唯一性，还会自动创建索引，并且不允许为空值。唯一约束则允许空值，但也会确保列中的值是唯一的。在实际开发中，根据需求选择主键和唯一约束，能够有效地维护数据的完整性和避免重复数据。
