SQL简介
约 4050 字大约 14 分钟
2025-07-25
- 全称:Structured Query Language,结构化查询语言。
- 作用:操作关系型数据库的编程语言,定义了一套操作关系型数据库的统一标准。
2.1 SQL 通用语法
- SQL 语句可以单行或多行书写,以分号
;
结尾。 - SQL 语句可以使用空格或缩进来增强可读性。
- MySQL 数据库的 SQL 语句不区分大小写,但关键字建议使用大写。
- 注释:
- 单行注释:
-- 注释内容
或# 注释内容
- 多行注释:
/* 注释内容 */
- 单行注释:
2.2 SQL 分类
SQL 语句根据其功能主要分为四类:DDL、DML、DQL、DCL。
分类 | 全称 | 说明 |
---|---|---|
DDL | Data Definition Language | 数据定义语言,用来定义数据库对象(数据库、表、字段)。 |
DML | Data Manipulation Language | 数据操作语言,用来对数据库表中的数据进行增删改。 |
DQL | Data Query Language | 数据查询语言,用来查询数据库中表的记录。 |
DCL | Data Control Language | 数据控制语言,用来创建数据库用户、控制数据库的访问权限。 |
接下来,我们将分别介绍这四类 SQL 语句的具体用法。
2.3 DDL(数据定义语言)
Data Definition Language,数据定义语言,用来定义数据库对象(数据库、表、字段)。本节将主要介绍如何使用 DDL 进行数据库操作。
2.3.1 数据库操作
查询所有数据库
show databases;
执行该语句后,会显示当前 MySQL 服务器中的所有数据库列表。
查询当前数据库
select database();
执行该语句后,会显示当前正在使用的数据库名称。
创建数据库
create database [if not exists] 数据库名 [default charset 字符集] [collate 排序规则];
if not exists
:如果数据库不存在,则创建,避免重复创建报错。default charset
:指定数据库的字符集,常用的字符集有utf8
、utf8mb4
等。
删除数据库
drop database [if exists] 数据库名;
if exists
:如果数据库存在,则删除,避免数据库不存在时报错。
切换数据库
use 数据库名;
在操作某个数据库下的表时,需要先切换到该数据库。
2.3.2 表操作
2.3.2.1 表操作 - 查询创建
查询当前数据库所有表
show tables;
该语句会列出当前所选数据库中的所有表。
查看指定表结构
desc 表名;
该语句会显示指定表的字段、类型、是否允许为空、默认值等信息。
查询指定表的建表语句
show create table 表名;
该语句会显示创建指定表的 SQL 语句,包括表的字段、类型、字符集、存储引擎等信息。
创建表结构
CREATE TABLE 表名( 字段1 字段1类型 [COMMENT 字段1注释], 字段2 字段2类型 [COMMENT 字段2注释], ... 字段n 字段n类型 [COMMENT 字段n注释] ) [COMMENT 表注释];
COMMENT
:为字段或表添加注释,方便理解。- 最后一个字段后面没有逗号。
2.3.2.2 表操作 - 数据类型
在定义表结构时,需要为每个字段指定数据类型。MySQL 中常见的数据类型包括数值类型、字符串类型和日期时间类型。
数值类型如下:
类型 | 大小 | 有符号 (SIGNED) 范围 | 无符号 (UNSIGNED) 范围 | 描述 |
---|---|---|---|---|
TINYINT | 1 byte | (-128, 127) | (0, 255) | 小整数值 |
SMALLINT | 2 bytes | (-32768, 32767) | (0, 65535) | 大整数值 |
MEDIUMINT | 3 bytes | (-8388608, 8388607) | (0, 16777215) | 大整数值 |
INT /INTEGER | 4 bytes | (-2147483648, 2147483647) | (0, 4294967295) | 大整数值 |
BIGINT | 8 bytes | (-2^63, 2^63-1) | (0, 2^64-1) | 极大整数值 |
FLOAT | 4 bytes | (-3.402823466E+38, 3.402823466E+38) | 0 和 (1.175494351E-38, 3.402823466E+38) | 单精度浮点数值 |
DOUBLE | 8 bytes | (-1.7976931348623157E+308, 1.7976931348623157E+308) | 0 和 (2.2250738585072014E-308, 1.7976931348623157E+308) | 双精度浮点数值 |
DECIMAL | 依赖于 M 和 D 的值 | 依赖于 M 和 D 的值 | 小数值 (精确定点数) |
M
:精度,表示总共可以存储多少位数字。D
:标度,表示小数点后可以存储多少位数字。- 示例:
- 年龄字段可使用
TINYINT UNSIGNED
。 - 分数可以使用
DOUBLE(3,1)
。
- 年龄字段可使用
字符串类型如下:
类型 | 大小 | 描述 |
---|---|---|
CHAR | 0-255 bytes | 定长字符串 (需要指定长度) |
VARCHAR | 0-65535 bytes | 变长字符串 (需要指定长度) |
TINYBLOB | 0-255 bytes | 不超过 255 个字符的二进制数据 |
TINYTEXT | 0-255 bytes | 短文本字符串 |
BLOB | 0-65535 bytes | 二进制形式的长文本数据 |
TEXT | 0-65535 bytes | 长文本数据 |
MEDIUMBLOB | 0-16777215 bytes | 二进制形式的中等长度文本数据 |
MEDIUMTEXT | 0-16777215 bytes | 中等长度文本数据 |
LONGBLOB | 0-4294967295 bytes | 二进制形式的极大文本数据 |
LONGTEXT | 0-4294967295 bytes | 极大文本数据 |
CHAR
是定长字符串,VARCHAR
是变长字符串。CHAR
的性能更高。- 示例:
- 用户名可以使用
VARCHAR(50)
。 - 性别可以使用
CHAR(1)
。 - 手机号可以使用
CHAR(11)
。
- 用户名可以使用
日期时间类型如下:
类型 | 大小 | 范围 | 格式 | 描述 |
---|---|---|---|---|
DATE | 3 | 1000-01-01 到 9999-12-31 | YYYY-MM-DD | 日期值 |
TIME | 3 | -838:59:59 到 838:59:59 | HH:MM:SS | 时间值或持续时间 |
YEAR | 1 | 1901 到 2155 | YYYY | 年份值 |
DATETIME | 8 | 1000-01-01 00:00:00 到 9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 |
TIMESTAMP | 4 | 1970-01-01 00:00:01 到 2038-01-19 03:14:07 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值,时间戳 |
- 示例:
- 生日字段可以使用
DATE
类型。 - 创建时间可以使用
DATETIME
类型。
- 生日字段可以使用
2.3.2.3 表操作 - 案例
设计一张员工信息表,要求如下:
- 编号(纯数字)
- 员工工号(字符串类型,长度不超过 10 位)
- 员工姓名(字符串类型,长度不超过 10 位)
- 性别(男/女,存储一个汉字)
- 年龄(正常人年龄,不可能存储负数)
- 身份证号(二代身份证号均为 18 位,身份证中有 X 这样的字符)
- 入职时间(取值年月日即可)
对应的建表语句如下:
create table emp (
id int comment '编号',
workno varchar(10) comment '工号',
name varchar(10) comment '姓名',
gender char(1) comment '性别',
age tinyint unsigned comment '年龄',
idcard char(18) comment '身份证号',
entrydate date comment '入职时间'
) comment '员工表';
2.3.2.4 表操作 - 修改
添加字段
ALTER TABLE 表名 ADD 字段名 类型(长度) [COMMENT 注释] [约束];
修改数据类型
ALTER TABLE 表名 MODIFY 字段名 新数据类型(长度);
修改字段名和字段类型
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 新数据类型(长度) [COMMENT 注释] [约束];
删除字段
ALTER TABLE 表名 DROP 字段名;
修改表名
ALTER TABLE 表名 RENAME TO 新表名;
2.3.2.5 表操作 - 删除
删除表
DROP TABLE [IF EXISTS] 表名;
IF EXISTS
:只有表名存在时才会删除该表,否则不执行删除操作。
删除指定表,并重新创建表
TRUNCATE TABLE 表名;
2.4 图形化界面工具
略。
2.5 DML(数据操作语言)
DML 英文全称是 Data Manipulation Language (数据操作语言),用来对数据库中表的数据记录进行增、删、改操作。
2.5.1 添加数据
给指定字段添加数据
INSERT INTO 表名(字段名1, 字段名2, ...) VALUES (值1, 值2, ...);
给全部字段添加数据
INSERT INTO 表名 VALUES (值1, 值2, ...);
批量添加数据
INSERT INTO 表名(字段名1, 字段名2, ...) VALUES (值1,值2, ...),(值1,值2, ...),(值1,值2, ...); INSERT INTO 表名 VALUES (值1,值2, ...), (值1,值2, ...), (值1,值2, ...);
注意事项:
- 插入数据时,指定的字段顺序需要与值的顺序是一一对应的。
- 字符串和日期型数据应该包含在引号中。
- 插入的数据大小,应该在字段的规定范围内。
2.5.2 修改数据
修改数据的具体语法为:
UPDATE 表名 SET 字段名1 = 值1, 字段名2 = 值2, .... [WHERE 条件];
修改语句的条件可以有,也可以没有,如果没有条件,则会修改整张表的所有数据。
2.5.3 删除数据
删除数据的具体语法为:
DELETE FROM 表名 [WHERE 条件];
DELETE
语句的条件可以有,也可以没有,如果没有条件,则会删除整张表的所有数据。DELETE
语句不能删除某一个字段的值(可以使用UPDATE
,将该字段值置为NULL
即可)。
2.6 DQL(数据查询语言)
DQL 英文全称是 Data Query Language (数据查询语言),数据查询语言,用来查询数据库中表的记录。
在一个正常的业务系统中,查询操作的频次是要远高于增删改的,当我们去访问企业官网、电商网站,在这些网站中我们所看到的数据,实际都是需要从数据库中查询并展示的。而且在查询的过程中,可能还会涉及到条件、排序、分页等操作。
2.6.1 基本语法
DQL 查询语句,语法结构如下:
SELECT
字段列表
FROM
表名列表
WHERE
条件列表
GROUP BY
分组字段列表
HAVING
分组后条件列表
ORDER BY
排序字段列表
LIMIT
分页参数
2.6.2 基础查询
在基本查询的 DQL 语句中,不带任何的查询条件,查询的语法如下:
查询多个字段
SELECT 字段1,字段2,字段3 ... FROM 表名;
查询所有字段
SELECT * FROM 表名;
注意:
*
号代表查询所有字段,在实际开发中尽量少用(不直观、影响效率)。字段设置别名
SELECT 字段1 [AS 别名1], 字段2 [AS 别名2] ... FROM 表名; SELECT 字段1 [别名1], 字段2 [别名2] ... FROM 表名;
去除重复记录
SELECT DISTINCT 字段列表 FROM 表名;
2.6.3 条件查询
使用语法:
SELECT 字段列表 FROM 表名 WHERE 条件列表;
常用的比较运算符如下:
比较运算符 | 功能 |
---|---|
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
= | 等于 |
<> 或 != | 不等于 |
BETWEEN | 在某个范围之内,包含边界 |
IN | 在 IN 之后的列表中的值,多选一 |
LIKE | 模糊匹配(_ 匹配单个字符,% 匹配任意个字符) |
IS NULL | 是否为 NULL |
常用的逻辑运算符如下:
逻辑运算符 | 功能 |
---|---|
AND 或 && | 并且(多个条件同时成立) |
OR 或 | | 或者(多个条件任意一个成立) |
NOT 或 ! | 非,不是 |
2.6.4 聚合函数
聚合函数将一列数据作为一个整体,进行纵向计算:
SELECT 聚合函数(字段列表) FROM 表名;
注意:NULL
值是不参与所有聚合函数运算的。
常见的聚合函数如下:
函数 | 功能 |
---|---|
COUNT | 统计数量 |
MAX | 最大值 |
MIN | 最小值 |
AVG | 平均值 |
SUM | 求和 |
2.6.5 分组查询
分组查询的基本语法如下:
SELECT 字段列表 FROM 表名 [WHERE 条件] GROUP BY 分组字段名 [HAVING 分组后过滤条件];
该语法结构允许我们从指定的表中选取数据,并根据一个或多个字段将数据分组,然后对每个组应用聚合函数,并使用 HAVING
子句对分组后的结果进行过滤。
WHERE
子句和 HAVING
子句都用于过滤数据,但它们在执行时机和判断条件上有所不同:
执行时机不同:
WHERE
子句在分组之前进行过滤,不满足WHERE
条件的记录不会参与分组;而HAVING
子句在分组之后对结果进行过滤。判断条件不同:
WHERE
子句不能对聚合函数进行判断,因为它在聚合函数计算之前执行;而HAVING
子句可以对聚合函数的结果进行判断。
注意事项:
查询字段:在分组查询中,通常查询的字段为聚合函数和分组字段。查询其他字段通常没有实际意义,因为每个分组只返回一行结果,其他字段的值会是该组中某个记录的值,不代表整个组的特征。
执行顺序:SQL 查询的执行顺序通常是
WHERE > 聚合函数 > HAVING
。这意味着先通过WHERE
子句过滤数据,然后对过滤后的数据进行分组和聚合计算,最后使用HAVING
子句对分组后的结果进行过滤。多字段分组:
GROUP BY
子句支持多字段分组,语法为GROUP BY columnA, columnB
。这将按照columnA
和columnB
的组合对数据进行分组。例如,可以按照部门和职位对员工进行分组,以统计每个部门每个职位的平均工资。
2.6.6 排序查询
排序在日常开发中是非常常见的一个操作,有升序排序,也有降序排序。
SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1, 字段2 排序方式2;
ASC
:升序(默认值)DESC
:降序
注意事项:
- 如果是升序,可以不指定排序方式
ASC
。 - 如果是多字段排序,当第一个字段值相同时,才会根据第二个字段进行排序。
2.6.7 分页查询
分页操作在业务系统开发时,也是非常常见的一个功能,我们在网站中看到的各种各样的分页条,后台都需要借助于数据库的分页操作。
SELECT 字段列表 FROM 表名 LIMIT 起始索引, 查询记录数 ;
注意事项:
- 起始索引从 0 开始,起始索引 = (查询页码 - 1) * 每页显示记录数。
- 分页查询是数据库的方言,不同的数据库有不同的实现,MySQL 中是
LIMIT
。 - 如果查询的是第一页数据,起始索引可以省略,直接简写为
LIMIT 10
。
2.6.8 案例
查询年龄为 20,21,22,23 岁的员工信息。
select * from emp where gender = '女' and age in (20,21,22,23);
查询性别为男,并且年龄在 20-40 岁(含)以内的姓名为三个字的员工。
select * from emp where gender = '男' and (age between 20 and 40 ) and name like '___';
2.6.9 执行顺序
在讲解 DQL 语句的具体语法之前,已经讲解了 DQL 语句的完整语法,及编写顺序,接下来,要来说明的是 DQL 语句在执行时的执行顺序,也就是先执行那一部分,后执行那一部分。
DQL 语句的执行顺序:from -> where -> group by -> having -> select -> order by -> limit
2.7 DCL(数据控制语言)
DCL 英文全称是 Data Control Language (数据控制语言),用来管理数据库用户、控制数据库的访问权限。
2.7.1 管理用户
查询用户
select * from mysql.user;
在查询结果中,Host 代表当前用户访问的主机,如果为
localhost
,代表其只能够在当前本机访问,无法远程访问。User 代表的是访问该数据库的用户名。在 MySQL 中需要通过 Host 和 User 来唯一标识一个用户。创建用户
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
修改用户密码
ALTER USER '用户名'@'主机名' IDENTIFIED WITH mysql_native_password BY '新密码';
删除用户
DROP USER '用户名'@'主机名';
在 MySQL 中需要通过
用户名@主机名
的方式,来唯一标识一个用户。
2.7.2 权限控制
MySQL 中定义了很多种权限,但是常用的就以下几种:
权限 | 说明 |
---|---|
ALL, ALL PRIVILEGES | 所有权限 |
SELECT | 查询数据 |
INSERT | 插入数据 |
UPDATE | 修改数据 |
DELETE | 删除数据 |
ALTER | 修改表 |
DROP | 删除数据库/表/视图 |
CREATE | 创建数据库/表 |
查询权限
SHOW GRANTS FOR '用户名'@'主机名';
授予权限
GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'主机名';
撤销权限
REVOKE 权限列表 ON 数据库名.表名 FROM '用户名'@'主机名';
注意事项:
- 多个权限之间,使用逗号分隔
- 授权时, 数据库名和表名可以使用
*
进行通配,代表所有。