MySQL: MySQL数据表创建与约束详解
最后更新:2026-08-26
表是数据库中存储数据的基本单位——设计好表结构,数据管理就成功了一半。
本课带你掌握表的创建、约束设置和结构查看。
graph TB
A[CREATE TABLE 要素] --> B[列定义<br/>字段名+数据类型]
A --> C[约束定义]
C --> D[PRIMARY KEY 主键]
C --> E[FOREIGN KEY 外键]
C --> F[UNIQUE 唯一]
C --> G[NOT NULL 非空]
C --> H[DEFAULT 默认值]
C --> I[CHECK 检查]
A --> J[表选项<br/>ENGINE/CHARSET/COMMENT]
1. 你将学到
- CREATE TABLE 完整语法
- 主键约束(PRIMARY KEY)
- 外键约束(FOREIGN KEY)
- 唯一约束(UNIQUE)
- 非空约束(NOT NULL)
- 查看表结构
2. 一个电商系统的真实故事
(1) 痛点:数据混乱
一个电商数据库只有 orders 表,把客户信息、商品信息都塞进去:
| order_id | customer_name | customer_phone | product_name | product_price | quantity |
|---|---|---|---|---|---|
| 1 | Alice | 13800001111 | iPhone | 999 | 2 |
| 2 | Alice | 13800001111 | MacBook | 1999 | 1 |
| 3 | Bob | 13800002222 | iPhone | 999 | 1 |
问题:
- Alice 的电话号码存了 3 次,改号要改 3 行
- iPhone 价格存了 2 次,涨价要改多行
- 没法统计"某个商品卖了多少"
(2) 规范化的解法
拆分成 3 张表,用外键关联:
SQL
-- 客户表
CREATE TABLE customers (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
phone VARCHAR(20) UNIQUE
);
-- 商品表
CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL
);
-- 订单表
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
customer_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT DEFAULT 1,
FOREIGN KEY (customer_id) REFERENCES customers(id),
FOREIGN KEY (product_id) REFERENCES products(id)
);
3. CREATE TABLE 语法
(1) 完整语法
SQL
CREATE TABLE [IF NOT EXISTS] table_name (
column1 datatype [constraints],
column2 datatype [constraints],
...
[table_constraints]
) [ENGINE=InnoDB] [DEFAULT CHARSET=utf8mb4];
▶ 示例:创建用户表
SQL
CREATE TABLE IF NOT EXISTS users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL,
password_hash VARCHAR(255) NOT NULL,
age INT CHECK (age >= 0 AND age <= 150),
status ENUM('active', 'inactive', 'banned') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
输出:
TEXT
📖 仅展示
Query OK, 0 rows affected (0.02 sec)
4. 主键约束(PRIMARY KEY)
主键是表中唯一标识每行的列,不能重复,不能为 NULL。
(1) 主键类型
| 类型 | 说明 | 示例 |
|---|---|---|
| 单列主键 | 一个字段做主键 | id INT PRIMARY KEY |
| 复合主键 | 多个字段组合作主键 | PRIMARY KEY (order_id, product_id) |
| 自增主键 | 自动生成递增 ID | id INT AUTO_INCREMENT PRIMARY KEY |
▶ 示例:主键用法
SQL
-- 单列主键
CREATE TABLE categories (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL
);
-- 复合主键
CREATE TABLE order_items (
order_id INT,
product_id INT,
quantity INT,
PRIMARY KEY (order_id, product_id)
);
5. 外键约束(FOREIGN KEY)
外键用于建立表与表之间的关系,保证数据完整性。
(1) 外键级联操作
| 操作 | 说明 |
|---|---|
| CASCADE | 主表删除/更新时,从表同步删除/更新 |
| SET NULL | 主表删除时,从表外键设为 NULL |
| RESTRICT | 有从表记录时禁止删除主表(默认) |
| NO ACTION | 同 RESTRICT |
▶ 示例:外键级联
SQL
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
customer_id INT,
order_date DATE,
FOREIGN KEY (customer_id) REFERENCES customers(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
-- 删除客户时,该客户的所有订单自动删除
DELETE FROM customers WHERE id = 1;
-- orders 表中 customer_id=1 的记录自动删除
6. 唯一约束(UNIQUE)
唯一约束确保列中的值不重复(但允许 NULL)。
▶ 示例:唯一约束
SQL
CREATE TABLE users (
id INT PRIMARY KEY,
email VARCHAR(100) UNIQUE, -- 单列唯一
username VARCHAR(50) UNIQUE, -- 单列唯一
phone VARCHAR(20),
UNIQUE KEY (phone) -- 另一种写法
);
-- 复合唯一约束
CREATE TABLE user_roles (
user_id INT,
role_id INT,
UNIQUE KEY (user_id, role_id) -- 同一用户不能重复分配同一角色
);
7. 非空约束(NOT NULL)
非空约束确保列不能存储 NULL 值。
▶ 示例:非空约束
SQL
CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL, -- 商品名必填
price DECIMAL(10,2) NOT NULL, -- 价格必填
description TEXT, -- 描述可为空
category_id INT NOT NULL
);
-- 插入测试
INSERT INTO products (name, price) VALUES ('iPhone', 999);
-- 错误:category_id 不能为 NULL
-- ERROR 1048 (23000): Column 'category_id' cannot be null
8. 默认值约束(DEFAULT)
▶ 示例:默认值
SQL
CREATE TABLE articles (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(200) NOT NULL,
status ENUM('draft', 'published', 'archived') DEFAULT 'draft',
view_count INT DEFAULT 0,
is_featured BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 插入时省略有默认值的字段
INSERT INTO articles (title) VALUES ('My First Article');
-- 查询
SELECT * FROM articles;
输出:
TEXT
📖 仅展示
+----+-------------------+--------+------------+-------------+---------------------+
| id | title | status | view_count | is_featured | created_at |
+----+-------------------+--------+------------+-------------+---------------------+
| 1 | My First Article | draft | 0 | 0 | 2026-07-03 10:00:00 |
+----+-------------------+--------+------------+-------------+---------------------+
9. CHECK 约束(MySQL 8.0+)
CHECK 约束确保列值满足指定条件。
▶ 示例:CHECK 约束
SQL
CREATE TABLE employees (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
age INT CHECK (age >= 18 AND age <= 65),
salary DECIMAL(10,2) CHECK (salary > 0),
email VARCHAR(100) CHECK (email LIKE '%@%.%')
);
-- 测试
INSERT INTO employees (name, age, salary, email) VALUES ('Alice', 25, 5000, 'alice@company.com');
-- 错误:age 不满足 CHECK 条件
INSERT INTO employees (name, age, salary, email) VALUES ('Bob', 15, 3000, 'bob@company.com');
-- ERROR 3819: Check constraint 'employees_chk_1' is violated.
10. 查看表结构
▶ 示例:查看表信息
SQL
-- 查看当前数据库所有表
SHOW TABLES;
-- 查看表结构
DESCRIBE users;
-- 或
DESC users;
-- 查看创建表的语句
SHOW CREATE TABLE users\G
-- 查看表的列信息
SHOW COLUMNS FROM users;
输出:
TEXT
📖 仅展示
+----------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+-------------------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| username | varchar(50) | NO | UNI | NULL | |
| email | varchar(100) | NO | | NULL | |
| password_hash | varchar(255) | NO | | NULL | |
| age | int | YES | | NULL | |
| status | enum(...) | YES | | active | |
| created_at | timestamp | YES | | CURRENT_TIMESTAMP | |
| updated_at | timestamp | YES | | CURRENT_TIMESTAMP | |
+----------------+--------------+------+-----+-------------------+----------------+
❓ 常见问题
Q 主键用自增 INT 还是 UUID?
A 推荐自增 INT/BIGINT(性能好、存储小)。UUID 适合分布式场景但会降低索引性能。
Q 一张表可以有多个 UNIQUE 吗?
A 可以。UNIQUE 可以有多个,但 PRIMARY KEY 只能有一个。
Q 外键会影响性能吗?
A 会有一点影响(每次写入需检查约束),但保证了数据完整性。高并发场景可在应用层检查。
Q NULL 和空字符串有什么区别?
A NULL 表示"没有值",空字符串 '' 是一个值。NULL 不能用 = 比较,需用 IS NULL。
Q 表名用单数还是复数?
A 推荐复数(users, orders),表示"一组记录"。保持整个项目风格一致即可。
📖 小节
- CREATE TABLE 创建表,需指定列名、数据类型和约束
- PRIMARY KEY 主键唯一标识每行,推荐自增 INT
- FOREIGN KEY 外键建立表关系,支持 CASCADE/SET NULL/RESTRICT
- UNIQUE 唯一约束确保列值不重复
- NOT NULL 非空约束确保列不存储 NULL
- DEFAULT 默认值在插入时自动填充
- CHECK 约束(8.0+)确保列值满足条件
- DESCRIBE 查看表结构,SHOW CREATE TABLE 查看完整定义
📝 作业
-
基础题(难度⭐):创建
students表,包含 id(自增主键)、name(非空)、age(CHECK 18-100)、email(唯一)。 -
进阶题(难度⭐⭐):创建
courses表和student_courses关联表(多对多),设置外键约束,删除学生时级联删除选课记录。 -
挑战题(难度⭐⭐⭐):设计一个博客系统的表结构(users、posts、comments、tags),包含主键、外键、非空、默认值等约束。