# 默认值与检查

URL: https://caijiao.org/postgresql/advanced/constraints/check
Source: docs/postgresql/advanced/constraints/check.md
Description: 介绍 PostgreSQL 中的默认值与检查约束，帮助开发者理解如何确保列值的默认填充和对数据进行有效性检查。

在 PostgreSQL 中，默认值（Default Value）和检查约束（Check Constraint）是确保数据完整性和有效性的两个重要机制。默认值允许在插入数据时，如果没有显式提供某列的值，则使用预定义的值。检查约束则用于限制列的值，确保数据符合一定的条件。

## 默认值 (Default Value)

默认值用于在插入数据时，如果没有为某个列指定值，则自动使用预定义的默认值。这可以避免遗漏列的情况，并确保列始终有一个有效的值。

### 设置默认值

在创建表时，可以使用 `DEFAULT` 关键字来为列指定默认值：

```sql
CREATE TABLE users (
  user_id SERIAL PRIMARY KEY,
  username VARCHAR(100) NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
````

在这个示例中，`created_at` 列的默认值是当前时间（`CURRENT_TIMESTAMP`）。如果在插入数据时没有提供 `created_at` 的值，PostgreSQL 会自动使用当前时间作为默认值。

### 常见的默认值类型

* **常量值**：可以为列指定常量值作为默认值，例如数字、字符串、布尔值等。

  ```sql
  CREATE TABLE products (
    product_id SERIAL PRIMARY KEY,
    price DECIMAL DEFAULT 0.0
  );
  ```

* **函数值**：可以使用数据库函数作为默认值，例如当前时间、随机数等。

  ```sql
  CREATE TABLE events (
    event_id SERIAL PRIMARY KEY,
    event_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  );
  ```

* **NULL 值**：如果没有为某列提供默认值，PostgreSQL 会使用 `NULL` 作为默认值，除非列定义中有 `NOT NULL` 约束。

  ```sql
  CREATE TABLE employees (
    employee_id SERIAL PRIMARY KEY,
    department_id INT DEFAULT NULL
  );
  ```

### 修改默认值

如果需要修改某个列的默认值，可以使用 `ALTER TABLE`：

```sql
ALTER TABLE users
ALTER COLUMN created_at SET DEFAULT CURRENT_TIMESTAMP;
```

### 删除默认值

如果希望删除某个列的默认值，可以使用以下命令：

```sql
ALTER TABLE users
ALTER COLUMN created_at DROP DEFAULT;
```

## 检查约束 (Check Constraint)

检查约束用于限制列的值，确保插入的数据符合指定的条件。通过检查约束，可以有效地控制数据的有效性，防止插入无效或错误的数据。

### 创建检查约束

在创建表时，可以使用 `CHECK` 关键字为列定义检查约束。例如，以下约束确保 `age` 列的值大于或等于 18：

```sql
CREATE TABLE employees (
  employee_id SERIAL PRIMARY KEY,
  name VARCHAR(100),
  age INT,
  CHECK (age >= 18)
);
```

在这个示例中，`CHECK (age >= 18)` 确保 `age` 列的值不能小于 18。

### 常见的检查约束应用

* **范围检查**：限制数值或日期在某个范围内。

  ```sql
  CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    order_date DATE,
    amount DECIMAL CHECK (amount > 0)
  );
  ```

* **字符串长度检查**：限制字符串的长度。

  ```sql
  CREATE TABLE products (
    product_id SERIAL PRIMARY KEY,
    product_name VARCHAR(100),
    CHECK (LENGTH(product_name) <= 100)
  );
  ```

* **正则表达式检查**：确保字符串符合特定的模式。

  ```sql
  CREATE TABLE users (
    user_id SERIAL PRIMARY KEY,
    email VARCHAR(100),
    CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$')
  );
  ```

  在这个示例中，`CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$')` 用正则表达式检查电子邮件地址的格式。

### 修改检查约束

可以使用 `ALTER TABLE` 命令来修改检查约束：

```sql
ALTER TABLE employees
ADD CONSTRAINT age_check CHECK (age >= 21);
```

### 删除检查约束

如果要删除检查约束，可以使用以下命令：

```sql
ALTER TABLE employees
DROP CONSTRAINT age_check;
```

## 组合默认值与检查约束

在表设计中，有时需要同时使用默认值和检查约束来确保数据有效性。例如，创建一个表，要求某列有默认值，并且该值必须在一定范围内：

```sql
CREATE TABLE products (
  product_id SERIAL PRIMARY KEY,
  price DECIMAL DEFAULT 0.0 CHECK (price >= 0)
);
```

在这个示例中，`price` 列的默认值为 `0.0`，同时检查约束确保该列的值大于或等于 0。

## 小结

默认值和检查约束是 PostgreSQL 中确保数据完整性和有效性的强大工具。通过默认值，可以确保列始终有一个有效值，减少遗漏数据的风险；通过检查约束，可以强制执行特定的规则，确保数据的有效性。在设计数据库时，合理使用默认值和检查约束，有助于提高数据的质量和一致性。
