MySQL 基础:DDL、DML、DQL、DCL 四大类 SQL 语句全解析
摘要:本文先介绍数据库 SQL 的核心概念,接着阐述 SQL 通用语法与 DDL、DML、DQL、DCL 四大分类,随后详细讲解各类语句操作,包括 DDL 的数据库与表操作及数据类型,DML 的数据增删改,DQL 的查询语法与功能,DCL 的用户管理和权限控制,助力掌握 MySQL 基础操作。
思维导图
1. MySQL 概述
1.1 数据库相关概念
本部分将讲解三个核心概念:数据库、数据库管理系统、SQL。
名称 | 全称 | 简称 |
---|---|---|
数据库 | 存储数据的仓库,数据是有组织的进行存储 | DataBase |
数据库管理系统 | 操纵和管理数据库的大型软件 | DataBase Management System |
SQL | 操作关系型数据库的编程语言,定义了一套操作关系型数据库统一标准 | Structured Query Language |
2. SQL语句
全称 Structured Query Language(结构化查询语言),是操作关系型数据库的编程语言,定义了一套操作关系型数据库的统一标准。无论使用 Oracle、SQL Server 还是 MySQL 等关系型数据库,均可以通过 SQL 语言进行统一操作,因此掌握 SQL 可灵活适配不同关系型数据库场景。
2.1 SQL 通用语法
在学习具体 SQL 语句前,需先了解 SQL 语言的通用规则:
SQL 语句可单行或多行书写,必须以分号结尾;
可使用空格 / 缩进来增强语句可读性(不影响执行结果);
MySQL 中的 SQL 语句不区分大小写,建议关键字使用大写,提高辨识度;
2.2 SQL 分类
根据功能,SQL 语句主要分为四类:DDL、DML、DQL、DCL,具体说明如下:
分类 | 说明 |
---|---|
DDL | 用于定义数据库对象(数据库、表、字段),如创建 / 删除数据库、创建 / 修改表结构等 |
DML | 用于对数据库表中的数据进行增、删、改操作 |
DQL | 用于查询数据库表中的记录,是业务中使用频次最高的 SQL 类型 |
DCL | 用于管理数据库用户、控制数据库访问权限,如创建用户、授予 / 撤销权限等 |
2.3 DDL(数据定义语言)
DDL 主要用于操作数据库、表、字段等 “结构级” 对象,核心是 “定义结构”,不涉及具体数据。
2.3.1 数据库操作
1. 查询所有数据库
show databases;
执行结果会显示当前 MySQL 服务器中所有已创建的数据库,例如系统默认数据库 information_schema
、mysql
、sys
等。
2. 查询当前数据库
select database();
用于确认当前所处/正在使用的数据库上下文(若未切换数据库,返回 NULL
)。
3. 创建数据库
create database [ if not exists ] 数据库名 [ default charset 字符集 ] [ collate 排序规则 ];
易错点:数据库名称在【 if not exists 】后面
if not exists
:可选参数,避免重复创建同名数据库导致报错(若数据库已存在则不执行);default charset
:可选参数,指定数据库默认字符集;collate
:可选参数,指定字符排序规则(通常默认跟随字符集,无需手动设置)。
4. 删除数据库
drop database [ if exists ] 数据库名;
if exists
:可选参数,避免删除不存在的数据库导致报错(若数据库不存在则不执行操作)。
5. 切换数据库
use 数据库名;
操作某数据库下的表前,必须先通过 use
切换到该数据库上下文。
2.3.2 表操作
2.3.2.1 表操作 - 查询与创建
1. 查询当前数据库所有表
show tables;
需先通过 use
切换到目标数据库,否则无法查询表。
2. 查看指定表结构
desc 表名;
返回表的字段名、数据类型、是否允许为 NULL
、主键 / 外键、默认值等结构信息。
3. 查询指定表的建表语句
show create table 表名;
返回创建该表的完整 SQL 语句,包含默认存储引擎(如 InnoDB)、字符集等隐式配置。
4. 创建表结构
CREATE TABLE 表名(
字段1 字段1类型 [ COMMENT 字段1注释 ],
字段2 字段2类型 [ COMMENT 字段2注释 ],
...
字段n 字段n类型 [ COMMENT 字段n注释 ]
) [ COMMENT 表注释 ];
字段定义格式:
字段名 类型 [约束] [注释]
;最后一个字段后不能加逗号,否则会语法报错;
COMMENT
:可选参数,用于添加字段 / 表的说明,提高可读性。
2.3.2.2 表操作 - 数据类型
MySQL 中的数据类型主要分为三类:数值类型、字符串类型、日期时间类型,需根据业务场景选择合适的类型(如年龄用 TINYINT
,手机号用 CHAR(11)
)。
1. 数值类型
适用于存储整数、小数等数值数据,核心是 “节省存储空间” 和 “保证精度”。
类型 | 大小 | 有符号(SIGNED)范围 | 无符号(UNSIGNED)范围 | 描述 |
---|---|---|---|---|
TINYINT | 1byte | (-128, 127) | (0, 255) | 小整数值(如年龄、状态码) |
SMALLINT | 2bytes | (-32768, 32767) | (0, 65535) | 中整数值(如数量较少的 ID) |
MEDIUMINT | 3bytes | (-8388608, 8388607) | (0, 16777215) | 大整数值 |
INT/INTEGER | 4bytes | (-2147483648, 2147483647) | (0, 4294967295) | 常用大整数值(如用户 ID、订单 ID) |
BIGINT | 8bytes | (-2^63, 2^63-1) | (0, 2^64-1) | 极大整数值(如海量数据的 ID) |
FLOAT | 4bytes | (-3.4E+38, 3.4E+38) | 0 和 (1.2E-38, 3.4E+38) | 单精度浮点数(精度较低,不适合金额) |
DOUBLE | 8bytes | (-1.8E+308, 1.8E+308) | 0 和 (2.2E-308, 1.8E+308) | 双精度浮点数(精度较高,仍不适合金额) |
DECIMAL | 可变 | 依赖 M(精度)和 D(标度) | 依赖 M(精度)和 D(标度) | 定点小数(精确存储,适合金额、分数等) |
使用建议:
年龄:
TINYINT UNSIGNED
(无负数,范围 0-255 足够);分数(如满分 100,1 位小数):
DOUBLE(4,1)
(总长度 4,小数位 1,范围 0.0-100.0);金额(如保留 2 位小数):
DECIMAL(10,2)
(避免浮点数精度丢失)。
2. 字符串类型
适用于存储文本、符号等字符数据,核心是 “区分定长与变长”。
类型 | 大小 | 描述 |
---|---|---|
CHAR | 0-255 bytes | 定长字符串(指定长度后,无论实际值多长,均占用固定字节) |
VARCHAR | 0-65535 bytes | 变长字符串(仅占用实际值长度 + 1-2 字节的长度标识,节省空间) |
TINYTEXT | 0-255 bytes | 短文本(适合存储少量文字,如备注) |
TEXT | 0-65535 bytes | 长文本(适合存储文章、评论等) |
MEDIUMTEXT | 0-16777215 bytes | 中等长度文本 |
LONGTEXT | 0-4294967295 bytes | 极大文本(适合存储超大文本,如日志) |
TINYBLOB/BLOB/MEDIUMBLOB/LONGBLOB | 同对应 TEXT 类型 | 二进制数据(如图片、文件,不推荐直接存储,建议存文件路径) |
CHAR 与 VARCHAR 区别:
CHAR(10)
:存储 “abc” 时,仍占用 10 字节(空格填充),性能高;VARCHAR(10)
:存储 “abc” 时,仅占用 3 + 1 = 4 字节(1 字节标识长度),节省空间。
使用建议:
用户名(长度不定,最长 50):
VARCHAR(50)
;性别(固定值 “男 / 女”):
CHAR(1)
;手机号(固定 11 位):
CHAR(11)
。
3. 日期时间类型
适用于存储日期、时间或混合时间数据,核心是 “匹配业务场景精度”。
类型 | 大小 | 范围 | 格式 | 描述 |
---|---|---|---|---|
DATE | 3bytes | 1000-01-01 至 9999-12-31 | YYYY-MM-DD | 仅日期(如生日) |
TIME | 3bytes | -838:59:59 至 838:59:59 | HH:MM:SS | 仅时间(如打卡时间) |
YEAR | 1byte | 1901 至 2155 | YYYY | 仅年份(如毕业年份) |
DATETIME | 8bytes | 1000-01-01 00:00:00 至 9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 日期 + 时间(如订单创建时间,不依赖时区) |
TIMESTAMP | 4bytes | 1970-01-01 00:00:01 至 2038-01-19 03:14:07 | YYYY-MM-DD HH:MM:SS | 日期 + 时间(依赖时区,自动更新,适合记录 “最后修改时间”) |
使用建议:
生日:
DATE
;订单创建时间:
DATETIME
;数据最后修改时间:
TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
(自动更新)。
2.3.2.3 表操作 - 修改(修改表结构)
1. 添加字段
ALTER TABLE 表名 ADD 字段名 类型 (长度) [ COMMENT 注释 ] [ 约束 ];
2. 修改数据类型
ALTER TABLE 表名 MODIFY 字段名 新数据类型 (长度);
3. 修改字段名和数据类型
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 类型 (长度) [ COMMENT 注释 ] [ 约束 ];
可同时修改字段名和类型,需注意新旧字段名的顺序。
4. 删除字段
ALTER TABLE 表名 DROP 字段名;
5. 修改表名
ALTER TABLE 表名 RENAME TO 新表名;
核心:ALTER TABLE 表名 [ 操作 ] 字段名 类型
2.3.2.4 表操作 - 删除
1. 删除表
DROP TABLE [ IF EXISTS ] 表名;
if exists
:避免删除不存在的表导致报错。
2. 删除表并重新创建(清空数据 + 保留结构)
TRUNCATE TABLE 表名;
效果:删除表中所有数据,但保留表结构(相当于 “清空表”);
注意:数据无法恢复,且自增字段会重置为初始值(如 1)。
2.5 DML(数据操作语言)
DML 用于对表中的数据进行 “增、删、改” 操作,核心是 “操作数据”,不改变表结构。
2.5.1 添加数据(INSERT)
1. 给指定字段添加数据
INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...);
字段名与值必须一一对应(顺序、数量、类型需匹配);
字符串和日期类型的值必须用单引号包裹;
字段值需符合表结构约束。
2. 给全部字段添加数据(省略字段名)
INSERT INTO 表名 VALUES (值1, 值2, ...);
需按表中字段的默认顺序传入所有字段的值,不推荐(表结构变更后易报错)。
3. 批量添加数据
-- 方式1:指定字段批量插入
INSERT INTO 表名 (字段名1, 字段名2, ...)
VALUES (值1, 值2, ...), (值1, 值2, ...), (值1, 值2, ...);
-- 方式2:全部字段批量插入
INSERT INTO 表名
VALUES (值1, 值2, ...), (值1, 值2, ...), (值1, 值2, ...);
注意事项
字段顺序与值顺序必须一致;
字符串、日期类型必须用单引号包裹;
插入的值需符合字段约束(如长度、范围、非空等),否则报错。
2.5.2 修改数据(UPDATE)
UPDATE 表名 SET 字段名1 = 值1, 字段名2 = 值2, ... [ WHERE 条件 ];
WHERE
:可选参数,用于指定修改的范围(若省WHERE
,则修改表中所有数据,谨慎)。
注意事项
无
WHERE
条件会修改全表数据,生产环境中需严格校验条件;可同时修改多个字段,用逗号分隔字段赋值表达式。
2.5.3 删除数据(DELETE)
DELETE FROM 表名 [ WHERE 条件 ];
WHERE
:可选参数,指定删除的范围(若省略WHERE
,则删除表中所有数据!)。
注意事项
无
WHERE
条件会删除全表数据,且数据无法通过ROLLBACK
恢复(除非开启事务);DELETE
只能删除行数据,不能删除单个字段的值(需用UPDATE
将字段设为NULL
);DataGrip 等工具会对删除全表操作进行二次确认,避免误操作。
2.6 DQL(数据查询语言)
DQL 用于查询表中的记录,是业务中最常用的 SQL 类型,支持条件筛选、排序、分组、分页等复杂操作。
2.6.1 数据准备
先创建 emp
员工表并插入测试数据,后续案例基于该表展开。
2.6.2 DQL 基本语法
完整 DQL 语法结构(按编写顺序):
SELECT
字段列表 -- 要查询的字段(如 name, age 或 * 表示所有字段)
FROM
表名列表 -- 要查询的表(单表查询仅需写表名)
WHERE
条件列表 -- 行级筛选条件(如 age > 20)
GROUP BY
分组字段列表 -- 按指定字段分组(如按 gender 分组)
HAVING
分组后条件列表 -- 分组后的筛选条件(如 count(*) > 5)
ORDER BY
排序字段列表 -- 按指定字段排序(如 age ASC 升序)
LIMIT
分页参数 -- 分页查询(如 LIMIT 0, 10 表示第 1 页,10 条/页)
执行顺序(与编写顺序不同,需重点理解):
FROM
→ WHERE
→ GROUP BY
→ HAVING
→ SELECT
→ ORDER BY
→ LIMIT
2.6.3 基础查询(无筛选条件)
1. 查询多个指定字段
SELECT 字段1, 字段2, ... FROM 表名;
2. 查询所有字段(不推荐)
SELECT * FROM 表名;
缺点:不直观、影响效率(若表字段多,会冗余返回不必要的字段),生产环境建议明确指定字段。
3. 字段设置别名
-- 方式1:使用 AS(推荐,可读性高)
SELECT 字段1 AS 别名1, 字段2 AS 别名2 FROM 表名;
-- 方式2:省略 AS(简洁)
SELECT 字段1 别名1, 字段2 别名2 FROM 表名;
别名含空格或特殊字符时,需用单引号包裹。
4. 去除重复记录
SELECT DISTINCT 字段列表 FROM 表名;
仅当所有指定字段的值完全相同时,才会被视为重复记录并去重。
2.6.4 条件查询(WHERE)
通过 WHERE
子句筛选符合条件的行数据,支持比较运算符和逻辑运算符。
1. 常用比较运算符
比较运算符 | 功能 |
---|---|
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
= | 等于 |
<> 或 != | 不等于 |
BETWEEN ... AND ... | 在指定范围(含边界) |
IN(...) | 在指定集合中 |
LIKE 占位符 | 模糊匹配 |
IS NULL | 为空 |
IS NOT NULL | 不为空 |
模糊匹配占位符:
`_`:匹配单个任意字符;
`%`:匹配 0 个或多个任意字符。
2. 常用逻辑运算符
逻辑运算符 | 功能 |
---|---|
AND 或 && | 并且(多个条件同时成立) |
OR 或 ` | ` |
NOT 或 ! | 非(否定条件) |
2.6.5 聚合函数
聚合函数用于对一列数据进行 “纵向计算”(将列数据视为一个整体),返回单个结果值。
1. 常用聚合函数
函数 | 功能 |
---|---|
count(字段) | 统计非 NULL 值的记录数 |
max(字段) | 求该列的最大值 |
min(字段) | 求该列的最小值 |
avg(字段) | 求该列的平均值 |
sum(字段) | 求该列的总和 |
注意:
NULL
值不参与任何聚合函数计算。
2. 语法
SELECT 聚合函数(字段列表) FROM 表名 [ WHERE 条件 ];
2.6.6 分组查询(GROUP BY)
通过 GROUP BY
按指定字段分组,将相同值的行归为一组,然后对每组进行聚合计算(如统计每组人数、平均年龄)。
1. 语法
SELECT 分组字段, 聚合函数(字段) FROM 表名 [ WHERE 条件 ] GROUP BY 分组字段 [ HAVING 分组后条件 ];
WHERE
:分组前的筛选条件(筛选行数据,不满足条件的行不参与分组);HAVING
:分组后的筛选条件(筛选分组结果,不满足条件的分组不显示)。
注意:前后的第一个查询字段必须相同,都为分组字段,第二个是聚合函数才有意义
2. WHERE 与 HAVING 的区别
对比维度 | WHERE | HAVING |
---|---|---|
执行时机 | 分组前 | 分组后 |
作用对象 | 行数据 | 分组结果 |
支持的条件 | 不能使用聚合函数 | 可以使用聚合函数 |
3. 注意事项
分组后查询的字段只能是 “分组字段” 或 “聚合函数”,查询其他字段无意义(结果不可控);
多字段分组时,按字段顺序依次分组(先按第一个字段分组,同组内再按第二个字段分组)。
2.6.7 排序查询(ORDER BY)
通过 ORDER BY
按指定字段对查询结果排序,支持升序和降序。
1. 语法
SELECT 字段列表 FROM 表名 [ WHERE 条件 ] [ GROUP BY 分组字段 ] [ HAVING 分组后条件 ] ORDER BY 字段1 排序方式1, 字段2 排序方式2 ...;
排序方式:
`ASC`:升序(默认,可省略);
`DESC`:降序;
多字段排序:先按字段 1 排序,字段 1 值相同的行再按字段 2 排序。
2.6.8 分页查询(LIMIT)
通过 LIMIT
实现分页查询(避免一次性返回大量数据,优化性能),仅 MySQL 支持(其他数据库如 Oracle 用 ROWNUM
)。
1. 语法
SELECT 字段列表 FROM 表名 [ 其他子句 ] LIMIT 起始索引, 查询记录数;
起始索引:从 0 开始(表示第 1 条数据的索引为 0);
计算公式:
起始索引 = (页码 - 1) * 每页记录数
;若查询第 1 页数据,起始索引可省略。
2.6.9 DQL 执行顺序验证
通过别名测试可确认 DQL 执行顺序:
FROM
→ WHERE
→ GROUP BY
→ HAVING
→ SELECT
→ ORDER BY
→ LIMIT
2.7 DCL(数据控制语言)
DCL 用于管理数据库用户和控制访问权限,主要由 DBA(数据库管理员)操作,开发人员使用较少。
2.7.1 管理用户
1. 查询用户
MySQL 中所有用户信息存储在系统数据库 mysql
的 user
表中:
select * from mysql.user;
核心字段:
`Host`:用户可访问的主机(`localhost` 表示仅本地访问,`%` 表示任意主机访问);
`User`:用户名;
`authentication_string`:用户密码(加密存储)。
注意:
Host + User
唯一标识一个用户(同一用户名,不同主机视为不同用户)。
2. 创建用户
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
主机名:
`localhost`:仅允许本地(当前服务器)访问;
`%`:允许任意主机访问(远程访问需开放 MySQL 端口 3306);
密码:长度至少 4 位(MySQL 8.0+ 默认密码策略较严格,需包含字母、数字、符号)。
3. 修改用户密码
ALTER USER '用户名'@'主机名' IDENTIFIED WITH mysql\_native\_password BY '新密码';
mysql_native_password
:指定密码加密方式(兼容旧版本客户端,MySQL 8.0+ 推荐)。
4. 删除用户
DROP USER '用户名'@'主机名';
注意事项
必须指定
主机名
(即使是%
),否则无法准确匹配用户;开发环境中避免创建
%
主机的用户(安全风险),建议仅允许指定 IP 访问。
2.7.2 权限控制
MySQL 定义了多种权限,常用权限如下:
权限 | 说明 |
---|---|
ALL 或 ALL PRIVILEGES | 所有权限 |
SELECT | 查询数据权限(仅 DQL) |
INSERT | 插入数据权限(仅 DML) |
UPDATE | 修改数据权限(仅 DML) |
DELETE | 删除数据权限(仅 DML) |
ALTER | 修改表结构权限(仅 DDL) |
DROP | 删除数据库 / 表 / 视图权限(仅 DDL) |
CREATE | 创建数据库 / 表权限(仅 DDL) |
1. 查询用户权限
SHOW GRANTS FOR '用户名'@'主机名';
2. 授予权限
GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'主机名';
权限列表:多个权限用逗号分隔(如
SELECT, INSERT
),ALL
表示所有权限;数据库名。表名:
`*.*`:所有数据库的所有表(全局权限);
`itcast.*`:`itcast` 数据库的所有表;
`itcast.emp`:`itcast` 数据库的 `emp` 表。
3. 撤销权限
REVOKE 权限列表 ON 数据库名.表名 FROM '用户名'@'主机名';
注意事项
授予 / 撤销权限后,无需重启 MySQL,权限立即生效;
开发环境中遵循 “最小权限原则”(如仅给查询需求的用户授予
SELECT
权限),避免权限过大导致安全风险。