一、数据库相关的 DDL
1. 创建数据库(带字符集和排序规则)
基础写法:CREATE DATABASE 数据库名;
复杂场景(指定字符集 / 排序规则,避免乱码):
sql
CREATE DATABASE IF NOT EXISTS mydb -- "IF NOT EXISTS":不存在时才创建,避免报错
CHARACTER SET utf8mb4 -- 字符集:utf8mb4支持所有Unicode字符(含emoji),优于utf8
COLLATE utf8mb4_general_ci; -- 排序规则:_general_ci不区分大小写(常用);_bin区分大小写
2. 修改数据库(仅改字符集 / 排序规则)
注意:MySQL 中无法修改数据库名 (需手动迁移数据),只能改字符集相关:
sql
ALTER DATABASE mydb
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
二、表相关的 DDL
表的 DDL 是最常用且复杂的部分,涉及创建表时的约束设计、后期修改表结构等。
1. 创建表
基础表结构需定义 "字段名、类型、约束",复杂场景会包含主键、外键、唯一键、非空、默认值、自增等约束,以及特殊类型(如时间戳、枚举):
sql
CREATE TABLE IF NOT EXISTS student (
id INT PRIMARY KEY AUTO_INCREMENT, -- 主键+自增
name VARCHAR(50) NOT NULL, -- 非空约束
gender ENUM('男','女') DEFAULT '男', -- 枚举类型(只能选指定值)+默认值
phone VARCHAR(20) UNIQUE, -- 唯一约束
class_id INT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 自动记录创建时间
-- 外键约束(关联class表的id)
FOREIGN KEY (class_id) REFERENCES class(id)
ON DELETE SET NULL -- 级联操作:当class表的id被删除时,此表的class_id设为NULL
);
2. 修改表结构
实际开发中表结构常需调整,ALTER TABLE
是核心命令,常见场景:
需求 | SQL 示例 |
---|---|
添加字段 | ALTER TABLE student ADD COLUMN age INT DEFAULT 0; |
删除字段 | ALTER TABLE student DROP COLUMN phone; |
修改字段类型 / 约束 | ALTER TABLE student MODIFY age TINYINT NOT NULL; |
重命名字段 | ALTER TABLE student CHANGE age stu_age INT; (CHANGE 可改字段名 + 类型) |
重命名表 | ALTER TABLE student RENAME TO t_student; |
添加主键 | ALTER TABLE student ADD PRIMARY KEY (id); |
添加唯一键 | ALTER TABLE student ADD UNIQUE (name); |
添加外键 | ALTER TABLE student ADD FOREIGN KEY (class_id) REFERENCES class(id); |
三、索引相关的 DDL
索引是提升查询效率的关键,DDL 中需掌握 "创建 / 删除索引" 的操作:
1. 创建索引
- 普通索引(最常用):CREATE INDEX
idx_student_name ON student(name);
- 唯一索引(字段值唯一):
CREATE UNIQUE INDEX idx_student_phone ON student(phone);
- 联合索引(多字段组合):
CREATE INDEX idx_name_age ON student(name, age);
(查询时需符合 "最左前缀原则")
2. 删除索引
sql
DROP INDEX idx_student_name ON student;
3. 注意
- 索引能加速查询,但会降低 "插入 / 更新 / 删除" 效率(需维护索引);
- 小表无需建索引(查询快,索引反而占空间)。
四、视图相关的 DDL(虚拟表)
视图是 "查询结果的虚拟表",DDL 中用于创建 / 删除视图:
特点:视图仅保存查询逻辑,不存实际数据;适合简化复杂查询(如多表联查)。
五、DDL 的核心特性
- 自动提交事务 :执行 DDL 后会立即隐式提交事务,哪怕在
BEGIN
开启的手动事务中,也无法ROLLBACK
(如TRUNCATE TABLE
本质是 DDL,删数据后不可恢复); - 元数据改变:直接修改数据库的 "结构描述信息"(如表的字段定义、索引信息);
- 锁表风险 :执行
ALTER TABLE
等操作时,可能对表 加 排他锁(尤其大表),导致其他操作阻塞,需提前评估。
总结
DDL 的核心是 "操作结构",复杂场景集中在表的约束设计 (主键 / 外键 / 自增)、表结构修改 (ALTER TABLE)、索引创建(优化查询)这三部分。使用时需注意:DDL 操作不可逆(无回滚),修改生产环境表结构前必须备份数据,且避免高峰时段执行。
ALTER TABLE 修改表结构
ALTER TABLE
是 DDL 中用于修改表结构的核心命令,不同数据库(MySQL 5.7/8.0) 的语法存在差异,且有完整写法与简略写法的区分。
一、添加字段(ADD COLUMN)
作用:给表新增 1 个或多个字段(可指定 字段类型、约束、位置)。
1. 标准 SQL 基础写法(通用)
sql
-- 完整写法(带COLUMN关键字)
ALTER TABLE 表名
ADD COLUMN 字段名 类型 [约束];
-- 简略写法(省略COLUMN)
ALTER TABLE 表名
ADD 字段名 类型 [约束];
2. MySQL 特有(支持多字段 + 位置指定)
- 多字段同时添加 :MySQL 支持在 1 条
ADD
后用逗号分隔多个字段(Oracle 不支持,需分多条写); - 指定字段位置 :用
AFTER 已有字段
(插在某字段后)或FIRST
(插在第 1 位)。
sql
-- MySQL 5.7/8.0通用
-- 1. 单字段+位置+约束 (简略写法)
ALTER TABLE student
ADD age INT NOT NULL DEFAULT 0 AFTER name; -- 插在name字段后
-- 2. 多字段同时添加(完整写法)
ALTER TABLE student
ADD COLUMN email VARCHAR(100) UNIQUE,
ADD COLUMN create_time DATETIME; -- 第2个字段(默认插在表末尾)
二、修改字段(MODIFY COLUMN / CHANGE COLUMN)
作用:修改字段的类型、约束(如非空、默认值),或重命名字段(需特殊语法)。
1. 仅修改类型 / 约束(不改名):MODIFY
标准 SQL 基础写法 (可省略 COLUMN):
sql
-- 完整写法
ALTER TABLE 表名
MODIFY COLUMN 字段名 新类型 [新约束];
-- 简略写法(省略COLUMN)
ALTER TABLE 表名
MODIFY 字段名 新类型 [新约束];
MySQL
- MySQL 支持同时修改多个字段(用逗号分隔);
sql
-- MySQL 5.7/8.0(多字段同时修改)
ALTER TABLE student
MODIFY age TINYINT DEFAULT 18, -- 改age类型为TINYINT,默认值18
MODIFY name VARCHAR(60) NOT NULL; -- 改name长度为60,加非空
2. 重命名字段(同时可改类型 / 约束):
- MySQL 5.7 :仅支持
CHANGE COLUMN
(需同时指定 "旧字段名 + 新字段名 + 新类型",哪怕类型不变); - MySQL 8.0 :新增
RENAME COLUMN
注意:
- MySQL 5.7 的
CHANGE
必须带 "新类型"(哪怕和旧类型一样),否则报错; - MySQL 8.0 的
RENAME COLUMN
仅负责改名,改类型需单独用MODIFY
。
三、删除字段(DROP COLUMN)
作用:从表中删除 1 个或多个字段(删除后数据不可恢复)。
1. 标准 SQL 基础写法(通用)
sql
-- 完整写法
ALTER TABLE 表名
DROP COLUMN 字段名;
-- 简略写法(省略COLUMN)
ALTER TABLE 表名
DROP 字段名;
2. MySQL 特有(支持多字段同时删除)
MySQL 5.7/8.0 均支持用逗号分隔多个字段,1 条语句删除:
sql
-- 多字段删除(简略写法)
ALTER TABLE student
DROP age, --删除 第1个字段
DROP email; -- 删除 第2个字段
四、添加约束(主键 / 外键 / 唯一键 / 默认值)
1. 添加主键(PRIMARY KEY)
通用基础写法(可省略 CONSTRAINT 约束名):
sql
-- 完整写法 (指定约束名)
ALTER TABLE 表名
ADD CONSTRAINT 约束名 PRIMARY KEY (字段名);
-- 简略写法 (不指定约束名,数据库自动生成)
ALTER TABLE 表名
ADD PRIMARY KEY (字段名);
2. 添加外键(FOREIGN KEY)
通用基础写法(需指定关联表和字段):
sql
-- 完整写法
ALTER TABLE 子表名
ADD CONSTRAINT 外键约束名
FOREIGN KEY (子表字段)
REFERENCES 父表名 (父表字段)
[ON DELETE 级联操作]
[ON UPDATE 级联操作];
-- 级联操作:SET NULL/CASCADE/RESTRICT/No action/Set Default
示例:
sql
-- MySQL(支持ON UPDATE)
ALTER TABLE student
ADD CONSTRAINT fk_stu_class
FOREIGN KEY (class_id)
REFERENCES class (id)
ON DELETE SET NULL -- 父表id删除时,子表class_id设为NULL
ON UPDATE CASCADE; -- 父表id更新时,子表class_id同步更新
3. 添加唯一键(UNIQUE)
通用基础写法(可省略约束名):
sql
-- 完整写法
ALTER TABLE 表名
ADD CONSTRAINT 约束名 UNIQUE (字段名);
-- 简略写法
ALTER TABLE 表名
ADD UNIQUE (字段名);
五、删除约束(主键 / 外键 / 唯一键)
作用:移除表上的约束(需知道约束名,或通过系统表查询)。
1. 删除主键
通用写法 (主键约束名通常为PRIMARY
,无需显式指定):
sql
ALTER TABLE 表名
DROP PRIMARY KEY;
MySQL 若主键字段是自增(AUTO_INCREMENT
),删除主键后需先去掉自增(否则报错):
sql
-- MySQL需先改自增字段(否则DROP PRIMARY KEY报错)
ALTER TABLE student MODIFY id INT; -- 去掉AUTO_INCREMENT
ALTER TABLE student DROP PRIMARY KEY; -- 再删主键
2. 删除外键 / 唯一键
通用写法(必须指定约束名,无法省略):
sql
ALTER TABLE 表名
DROP CONSTRAINT 约束名;
六、重命名表(RENAME TO)
作用:修改表的名称。
MySQL 写法(5.7/8.0 通用,支持 2 种语法)
sql
-- 写法1(ALTER TABLE)
ALTER TABLE 旧表名 RENAME TO 新表名;
-- 写法2(RENAME TABLE,更简洁,支持多表同时改名)
RENAME TABLE 旧表名1 TO 新表名1, 旧表名2 TO 新表名2; -- 多表改名
Limit
1. LIMIT
的基础语法(2 种形式)
-
简洁写法 :
LIMIT 行数
直接返回查询结果的前 N 行。
例:查询
student
表的前 5 条数据sqlSELECT * FROM student LIMIT 5;
-
完整写法 :
LIMIT 偏移量, 行数
-
偏移量
:从第几条数据开始取(默认从 0 开始计数,即 "偏移量 = 0" 表示从第 1 条开始)。 -
行数
:取多少条数据。
例:查询student
表中,从第 6 条开始的 5 条数据(即第 6-10 条)SELECT * FROM student LIMIT 5, 5; -- 偏移量5(跳过前5条),取5条
-
2. 分页场景的核心公式(最重要)
分页时,通常需要根据 "当前页码" 和 "每页显示行数" 计算 LIMIT
的参数,公式为:
LIMIT (当前页码 - 1) * 每页行数, 每页行数
-
变量说明:
- 设
pageNum
= 当前页码(从 1 开始计数,如第 1 页、第 2 页); - 设
pageSize
= 每页显示的行数(如每页显示 10 条)。
- 设
-
例:
若要查询 "第 3 页,每页显示 10 条数据":
偏移量 = (3-1)*10 = 20,行数 = 10
SQL:
sqlSELECT * FROM student LIMIT 20, 10; -- 从第21条开始,取10条(第21-30条)
AUTO_INCREMENT的使用
一、MySQL 5.7 及更早版本
核心限制 :AUTO_INCREMENT
必须与主键(PRIMARY KEY
)绑定,否则会报错。
(即使尝试将自增字段设为非主键,MySQL 也会自动将其隐式设为主键,或直接拒绝)
1. 建表时定义自增主键(正确写法)
sql
-- MySQL 5.7 示例:自增字段 id 作为主键
CREATE TABLE student (
id INT NOT NULL AUTO_INCREMENT, -- 自增字段
name VARCHAR(50),
PRIMARY KEY (id) -- 必须绑定主键
);
2. 错误写法(非主键加自增)
sql
-- MySQL 5.7 会报错:
"Incorrect table definition;
there can be only one auto column and it must be defined as a key"
CREATE TABLE student (
id INT NOT NULL AUTO_INCREMENT, -- 自增字段
name VARCHAR(50),
PRIMARY KEY (name) -- 主键是 name,而非自增字段 id
);
二、MySQL 8.0 的改进
核心变化 :AUTO_INCREMENT
不再强制绑定主键,但必须有唯一索引 (UNIQUE
),否则可能产生重复值。
自增字段 + 唯一索引(非主键,正确写法)
sql
-- MySQL 8.0 示例:自增字段作为唯一业务标识,主键另设
CREATE TABLE order_info (
order_id INT NOT NULL AUTO_INCREMENT, -- 自增字段
order_no VARCHAR(50) NOT NULL, -- 实际主键
create_time DATETIME,
PRIMARY KEY (order_no), -- 主键是 order_no
UNIQUE INDEX idx_order_id (order_id) -- 自增字段必须有唯一索引
);
场景价值:这种设计适合 "业务主键(如订单号)+ 自增 ID(内部标识)" 的场景,兼顾业务可读性和数据库性能。
三、自增字段的其他关键特性(通用)
-
初始值与步长
可通过
AUTO_INCREMENT = N
设定初始值,步长由系统变量 auto_increment_increment 控制(默认 1):sql-- 建表时指定初始值 CREATE TABLE student ( id INT AUTO_INCREMENT, name VARCHAR(50), PRIMARY KEY (id) ) AUTO_INCREMENT = 100; -- 从100开始自增(100,101,102...)
-
重置自增值
需通过
ALTER TABLE
重置(仅影响后续插入,不改变已有数据):sql-- 将自增初始值重置为200(若已有数据id>200,则从最大id+1开始) ALTER TABLE student AUTO_INCREMENT = 200;