MySQL: MySQL数据表创建与约束详解

最后更新:2026-08-26

表是数据库中存储数据的基本单位——设计好表结构,数据管理就成功了一半。

本课带你掌握表的创建、约束设置和结构查看。

100%
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. 你将学到


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

问题:

(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),表示"一组记录"。保持整个项目风格一致即可。

📖 小节


📝 作业

  1. 基础题(难度⭐):创建 students 表,包含 id(自增主键)、name(非空)、age(CHECK 18-100)、email(唯一)。

  2. 进阶题(难度⭐⭐):创建 courses 表和 student_courses 关联表(多对多),设置外键约束,删除学生时级联删除选课记录。

  3. 挑战题(难度⭐⭐⭐):设计一个博客系统的表结构(users、posts、comments、tags),包含主键、外键、非空、默认值等约束。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏