# P33 33. 基础-约束-演示

> 本页是学习笔记，不等同于视频逐字稿。原声字幕未取得（匿名接口字幕轨为空且需登录，未使用任何账号），也没有逐句讲解记录；讲义只按节与页码对应，切点未逐句确证。

> 以同版讲义的公开镜像核对章节与页码（镜像非官方出品）；非逐字稿，示例为原创补充。

## P33 33. 基础-约束-演示

- 原视频：https://www.bilibili.com/video/BV1Kr4y1i7ru/?p=33（p=33），时长 15:00
- 讲义：4.2 约束演示 p62–64（公开镜像；按主题对应，切点 notexact）

- 本集练习数据：practice/p33.sql（先执行，再对照小例）

### 一句话理解

这一集把常用约束写进一张表（主键、非空、唯一、默认、CHECK；外键在 P34 单独讲），再故意插入坏数据，看数据库怎样拒绝。

### 步骤

1. 先建带约束的表：主键自增、姓名非空且唯一、年龄用 CHECK 限定范围、状态给默认值。
2. 先插合法数据，确认能进；再一次只违反一条规则，观察报错。
3. 对着错误码读原因：1062 是唯一冲突、1048 是非空、3819 是 CHECK 不通过。
4. 改回合法值再插一次，确认表仍可正常写入。

### SQL 示例

```
CREATE TABLE practice_user (
  id     INT PRIMARY KEY AUTO_INCREMENT,
  name   VARCHAR(10) NOT NULL UNIQUE,
  age    INT CHECK (age > 0 AND age <= 120),
  status CHAR(1) DEFAULT '1'
) ENGINE = InnoDB;

INSERT INTO practice_user (name, age) VALUES ('小甲', 19), ('小乙', 25);
```

说明：【原创演示】原创演示表，字段与视频里的 user 表相似，但表名和数据都不同。插入只给 name 和 age，id 由自增生成，status 取默认 '1'。下面三种插入应被拒绝：重复 name 报 1062 Duplicate entry；name 传 NULL 报 1048；age 传 130 报 3819 检查约束失败。这些结果已在隔离的 MySQL 8.0.46 测试实例逐条验证（1062/1048/3819）；你也可以用 p33.sql 在本地练习库复现。

### 易错点

- 以为 UNIQUE 只能有一个 NULL：唯一约束允许多行 NULL，因为 NULL 之间不算相等。
- 以为自增编号会回填：删掉最大 id 再插新行，编号继续往后走，不补空位。
- 以为 CHECK 会顺带拦住 NULL：表达式结果为未知时按通过处理，要连 NULL 一起挡就得再写 IS NOT NULL。

### 30 秒速记

建表带约束 → 插合法数据 → 逐条违反 → 读 1062/1048/3819；UNIQUE 允许多 NULL；自增不回填。

### 自测

1. 为什么重复插入同名会失败，而插入两个 NULL 姓名不会？
   - 答：name 同时有 NOT NULL 和 UNIQUE：NULL 先被 NOT NULL 挡住；如果只有 UNIQUE，多个 NULL 是被允许的，因为唯一性比较不把 NULL 当作相等。
2. 报 3819 说明什么？
   - 答：CHECK 的表达式对这条数据不成立（结果为假），数据库拒绝了写入；先看表达式范围和传入值。

### 材料与来源

- [平台视频页] P33 原视频页（BV1Kr4y1i7ru） https://www.bilibili.com/video/BV1Kr4y1i7ru/?p=33
- [官方文档] MySQL 8.0 Reference：CREATE TABLE https://dev.mysql.com/doc/refman/8.0/en/create-table.html

证据说明：按 t70 帧核对：画面是 Workbench 里执行建表 + 插入的演示，建表含主键自增、name 非空唯一、age 的 CHECK 范围、status 默认值，输出区出现 1062 Duplicate entry 报错。正文改用原创表名 practice_user 与自造数据，未照抄课堂表结构与姓名；无字幕，讲师逐步解说未核实。
