MySQL 入门笔记:DQL 基础查询与常用函数

今天的课程正式进入 MySQL。主要内容包括 MySQL 的基本概念、DQL 数据查询语言、条件查询、排序查询,以及字符串、数学和日期函数。

课程使用 myemployees 数据库中的 employees 员工表进行练习。表中包含员工编号、姓名、工资、奖金率、部门编号和入职日期等信息,非常适合用来学习 SQL 查询。


一、认识 MySQL 和数据库

数据库可以理解为按照一定结构保存数据的仓库。相比普通文本文件,数据库更适合保存大量数据,并且能够快速完成查询、修改和统计。

MySQL 是一种关系型数据库管理系统。所谓关系型数据库,就是把数据保存到一张张二维表中。

例如员工表:

employee_id first_name salary department_id
100 Steven 24000 90
101 Neena 17000 90
102 Lex 17000 90

其中:

一行表示一条记录;

一列表示一个字段;

表示同一类数据的多条记录保存在同一张表中;

多张表共同组成一个数据库。

SQL 语言可以分成几个部分:

DDL:定义数据库、表等结构;

DML:新增、修改和删除数据;

DQL:查询数据;

DCL:控制用户和权限;

TCL:控制事务。

今天主要学习的是 DQL,核心命令就是 SELECT


二、连接和选择数据库

在 Linux 中可以先检查 MySQL 服务状态:

复制代码
systemctl status mysqld

如果服务没有启动,可以执行:

复制代码
systemctl start mysqld

在终端中登录:

复制代码
mysql -uroot -p

查看服务器中有哪些数据库:

复制代码
SHOW DATABASES;

选择课程使用的数据库:

复制代码
USE myemployees;

查看当前数据库中的表:

复制代码
SHOW TABLES;

查看员工表的结构:

复制代码
DESC employees;

在 Navicat 等图形化工具中,也需要先选择连接和数据库,再创建查询窗口执行 SQL。


三、DQL 的基本查询语法

最基础的查询格式是:

复制代码
SELECT 查询列表
FROM 表名;

SELECT 表示选择哪些内容,FROM 表示从哪张表中查询。

1. 查询单个字段

复制代码
SELECT last_name
FROM employees;

2. 查询多个字段

复制代码
SELECT
    employee_id,
    first_name,
    last_name
FROM employees;

字段之间使用英文逗号分隔,最后一个字段后面不写逗号。

3. 查询所有字段

复制代码
SELECT *
FROM employees;

* 表示所有字段。练习时这样写比较方便,但在实际项目中更推荐写出需要的字段,减少无用数据的传输。

4. 查询常量和表达式

SELECT 不一定必须配合表使用:

复制代码
SELECT 100;
SELECT 'hello mysql';
SELECT 10 + 20;

还可以在查询表数据时进行计算:

复制代码
SELECT
    first_name,
    salary,
    salary * 12
FROM employees;

这里的 salary * 12 表示计算员工的基础年薪。


四、为查询结果设置别名

计算结果的默认列名通常不够直观,可以使用别名:

复制代码
SELECT
    first_name AS 姓名,
    salary AS 月薪,
    salary * 12 AS 年薪
FROM employees;

AS 可以省略:

复制代码
SELECT salary * 12 年薪
FROM employees;

如果别名中包含空格或特殊字符,应使用反引号:

复制代码
SELECT salary * 12 AS `annual salary`
FROM employees;

设置别名只会改变查询结果中的显示名称,不会修改原表字段。


五、MySQL 中加号的特点

在某些编程语言中,+ 既可以做加法,也可以拼接字符串。但 MySQL 中的 + 主要用于数学运算。

复制代码
SELECT 66 + 99;

结果为:

复制代码
165

当一边是数字字符串时,MySQL 会尝试把字符串转换为数字:

复制代码
SELECT 66 + '99';

结果仍然是:

复制代码
165

如果字符串不能正常转换为数字,通常会被转换成 0,并可能产生警告:

复制代码
SELECT 66 + 'abc';

另外,只要运算中出现 NULL,结果通常也是 NULL

复制代码
SELECT NULL + 70;

因此,拼接字符串不能依赖 +,应该使用 CONCAT()


六、字符串拼接和空值处理

查询员工的完整姓名:

复制代码
SELECT
    CONCAT(first_name, ' ', last_name) AS full_name
FROM employees;

如果希望自动添加分隔符,可以使用:

复制代码
SELECT
    CONCAT_WS('-', '2026', '08', '17') AS current_date;

结果为:

复制代码
2026-08-17

计算包含奖金的年薪时,需要注意 commission_pct 中可能存在空值。

复制代码
SELECT
    first_name,
    salary,
    salary * 12 * (1 + commission_pct) AS annual_salary
FROM employees;

当奖金率为 NULL 时,整个计算结果也会变成 NULL。可以使用 IFNULL()

复制代码
SELECT
    first_name,
    salary,
    salary * 12 * (1 + IFNULL(commission_pct, 0))
        AS annual_salary
FROM employees;

IFNULL(commission_pct, 0) 表示:如果奖金率为空,就使用 0 代替。


七、去除重复数据

如果只想查看员工所在的部门编号,可以使用:

复制代码
SELECT department_id
FROM employees;

但结果中会出现许多重复部门。使用 DISTINCT 可以去重:

复制代码
SELECT DISTINCT department_id
FROM employees;

DISTINCT 作用于后面所有字段的组合:

复制代码
SELECT DISTINCT department_id, job_id
FROM employees;

这表示去除"部门编号和职位编号都相同"的重复记录。


八、使用 WHERE 筛选数据

基本语法:

复制代码
SELECT 字段
FROM 表名
WHERE 条件;

例如查询工资大于 12000 的员工:

复制代码
SELECT
    employee_id,
    first_name,
    salary
FROM employees
WHERE salary > 12000;

常见比较运算符包括:

运算符 作用
= 等于
!=<> 不等于
> 大于
< 小于
>= 大于等于
<= 小于等于

例如查询部门编号不等于 90 的员工:

复制代码
SELECT
    first_name,
    department_id
FROM employees
WHERE department_id <> 90;

九、逻辑运算符

多个条件可以使用 ANDORNOT 连接。

查询工资大于 8000,并且部门编号为 80 的员工:

复制代码
SELECT
    first_name,
    salary,
    department_id
FROM employees
WHERE salary > 8000
  AND department_id = 80;

查询部门编号为 80 或 90 的员工:

复制代码
SELECT
    first_name,
    department_id
FROM employees
WHERE department_id = 80
   OR department_id = 90;

排除部门编号为 90 的员工:

复制代码
SELECT
    first_name,
    department_id
FROM employees
WHERE NOT department_id = 90;

同时使用 ANDOR 时,建议加上小括号,让条件更加明确:

复制代码
SELECT *
FROM employees
WHERE salary > 10000
  AND (department_id = 80 OR department_id = 90);

十、BETWEEN 和 IN

查询员工编号在 100 到 120 之间的记录:

复制代码
SELECT *
FROM employees
WHERE employee_id BETWEEN 100 AND 120;

BETWEEN 100 AND 120 包含边界,相当于:

复制代码
WHERE employee_id >= 100
  AND employee_id <= 120

查询职位编号属于几个指定值之一的员工:

复制代码
SELECT
    first_name,
    job_id
FROM employees
WHERE job_id IN ('IT_PROG', 'AD_VP', 'AD_PRES');

它相当于:

复制代码
WHERE job_id = 'IT_PROG'
   OR job_id = 'AD_VP'
   OR job_id = 'AD_PRES'

当同一个字段需要匹配多个确定值时,使用 IN 更简洁。


十一、LIKE 模糊查询

当我们只知道字符串的一部分时,可以使用 LIKE

% 表示任意数量的任意字符:

复制代码
SELECT first_name
FROM employees
WHERE first_name LIKE 'S%';

表示查询名字以 S 开头的员工。

复制代码
SELECT first_name
FROM employees
WHERE first_name LIKE '%a%';

表示名字中包含字母 a

下划线 _ 表示任意一个字符:

复制代码
SELECT first_name
FROM employees
WHERE first_name LIKE '_a%';

表示名字的第二个字符是 a

%_ 是通配符。如果要查询它们本身,需要进行转义。


十二、正确判断 NULL

NULL 表示缺失、未知或不存在,它不等于数字 0,也不等于空字符串。

错误写法:

复制代码
SELECT *
FROM employees
WHERE commission_pct = NULL;

正确写法:

复制代码
SELECT *
FROM employees
WHERE commission_pct IS NULL;

查询奖金率不为空的员工:

复制代码
SELECT *
FROM employees
WHERE commission_pct IS NOT NULL;

MySQL 还提供空值安全比较运算符 <=>

复制代码
SELECT *
FROM employees
WHERE commission_pct <=> NULL;

它可以用于普通值和 NULL,但为了提高可读性,判断空值时更推荐使用 IS NULL


十三、ORDER BY 排序查询

排序语法:

复制代码
SELECT 字段
FROM 表名
ORDER BY 排序字段 ASC或DESC;

ASC 表示升序,DESC 表示降序。如果不写,默认按照升序排列。

按工资从低到高排序:

复制代码
SELECT
    first_name,
    salary
FROM employees
ORDER BY salary ASC;

按工资从高到低排序:

复制代码
SELECT
    first_name,
    salary
FROM employees
ORDER BY salary DESC;

也可以按照表达式或别名排序:

复制代码
SELECT
    first_name,
    salary,
    salary * 12 * (1 + IFNULL(commission_pct, 0))
        AS annual_salary
FROM employees
ORDER BY annual_salary DESC;

多字段排序:

复制代码
SELECT
    first_name,
    department_id,
    salary
FROM employees
ORDER BY department_id ASC, salary DESC;

含义是先按部门升序,同一部门内再按工资降序。


十四、常用字符串函数

1. LENGTH 和 CHAR_LENGTH

复制代码
SELECT LENGTH('hello');
SELECT LENGTH('你好');

LENGTH() 返回字节数。英文一般一个字符占一个字节,而中文在 utf8mb4 中通常占多个字节。

如果想统计字符个数,可以使用:

复制代码
SELECT CHAR_LENGTH('你好');

2. 大小写转换

复制代码
SELECT UPPER('hello');
SELECT LOWER('MYSQL');

3. 截取字符串

复制代码
SELECT SUBSTR('hello mysql', 7, 5);

MySQL 字符串位置通常从 1 开始。以上语句会从第 7 个字符开始,截取 5 个字符。

4. 查找位置

复制代码
SELECT INSTR('hello mysql', 'mysql');

返回子字符串第一次出现的位置;没有找到时返回 0

5. 去除空格

复制代码
SELECT TRIM('  hello  ');

还可以删除指定字符:

复制代码
SELECT TRIM('x' FROM 'xxxhelloxxx');

6. 左右填充

复制代码
SELECT LPAD('数加', 4, '*');
SELECT RPAD('数加', 4, '*');

分别表示从左侧和右侧填充字符,直到达到指定长度。

7. 替换字符串

复制代码
SELECT REPLACE('hello mysql', 'mysql', 'database');

结果为:

复制代码
hello database

十五、常用数学函数

四舍五入:

复制代码
SELECT ROUND(3.1415926, 2);

向上取整:

复制代码
SELECT CEIL(3.14);
SELECT CEIL(-3.14);

向下取整:

复制代码
SELECT FLOOR(3.14);
SELECT FLOOR(-3.14);

直接截断小数,不进行四舍五入:

复制代码
SELECT TRUNCATE(123.456, 2);

计算余数:

复制代码
SELECT MOD(10, 3);

生成 01 之间的随机小数:

复制代码
SELECT RAND();

CEIL(-3.14) 的结果是 -3FLOOR(-3.14) 的结果是 -4。理解时不要简单记成"去掉小数",而要根据数轴方向判断。


十六、常用日期函数

获取当前日期和时间:

复制代码
SELECT NOW();

只获取当前日期:

复制代码
SELECT CURDATE();

只获取当前时间:

复制代码
SELECT CURTIME();

提取日期中的年、月、日:

复制代码
SELECT YEAR(NOW());
SELECT MONTH(NOW());
SELECT DAY(NOW());

提取时、分、秒:

复制代码
SELECT HOUR(NOW());
SELECT MINUTE(NOW());
SELECT SECOND(NOW());

计算两个日期相差的天数:

复制代码
SELECT DATEDIFF('2026-08-20', '2026-08-17');

十七、日期与字符串互相转换

1. STR_TO_DATE

将字符串转换成日期:

复制代码
SELECT STR_TO_DATE('2026-08-17', '%Y-%m-%d');

查询指定入职日期的员工:

复制代码
SELECT *
FROM employees
WHERE hiredate = STR_TO_DATE(
    '4-3-1992',
    '%c-%e-%Y'
);

2. DATE_FORMAT

将日期格式化成字符串:

复制代码
SELECT DATE_FORMAT(
    NOW(),
    '%Y年%m月%d日 %H:%i:%s'
);

常用格式符号:

格式 含义
%Y 四位年份
%y 两位年份
%m 两位月份
%c 数字月份
%d 两位日期
%e 数字日期
%H 24 小时制小时
%h 12 小时制小时
%i 分钟
%s

分钟使用 %i,而不是容易想当然写出的 %m,因为 %m 表示月份。


十八、综合查询案例

查询部门编号为 80 或 90、工资不低于 8000 的员工,显示完整姓名和年薪,并按年薪从高到低排列:

复制代码
SELECT
    employee_id,
    CONCAT_WS(' ', first_name, last_name) AS full_name,
    department_id,
    salary,
    salary * 12 * (1 + IFNULL(commission_pct, 0))
        AS annual_salary,
    DATE_FORMAT(hiredate, '%Y-%m-%d') AS hire_date
FROM employees
WHERE department_id IN (80, 90)
  AND salary >= 8000
ORDER BY annual_salary DESC;

分析一条查询时,可以按照下面的顺序思考:

复制代码
从哪张表查询
→ 查询哪些字段
→ 使用什么条件筛选
→ 是否需要计算或调用函数
→ 最后按照什么规则排序

总结

今天学习的核心是 SELECT 查询。最基础的结构是:

复制代码
SELECT 字段
FROM 表
WHERE 条件
ORDER BY 排序规则;

在此基础上,又学习了比较运算、逻辑运算、BETWEENINLIKE、空值判断以及排序。函数部分则包括字符串处理、数值计算和日期格式转换。

初学 SQL 时,最容易出现的问题包括:忘记字段之间的逗号、把字符串拼接写成加号、使用 = NULL 判断空值,以及没有注意 ANDOR 的优先级。练习时可以先用自然语言描述需求,再分别确定查询表、字段、条件和排序方式,最后组合成完整 SQL。

相关推荐
游戏开发爱好者819 小时前
WebSocket 抓包怎么查看内容?从握手到消息帧完整解读
网络协议·计算机网络·网络安全·ios·adb·https·udp
00后程序员张2 天前
SSL Pinning 抓包抓不到明文?绕过证书固定的几种方案
网络协议·计算机网络·网络安全·ios·adb·https·udp
没文化的阿浩3 天前
【MySQL】数据类型
android·mysql·adb
黄毛火烧雪下3 天前
智能眼镜无线adb调试
adb
游戏开发爱好者84 天前
带签名时间戳接口的重放与压力测试实战,用动态值在发送前现算签名
网络协议·计算机网络·网络安全·ios·adb·https·压力测试
Lethehong6 天前
MySQL迁移如何做到零改造?四层兼容方案详解
数据库·mysql·adb
陈卿诺语8 天前
MySQL错误-this is incompatible with sql_mode=only_full_group_by完美解决方案
sql·mysql·adb
2501_915921439 天前
抓包鹰 Traceeagle 解除证书绑定,SSL Pinning 解除
网络·网络协议·网络安全·ios·adb·https·ssl
Zhu75810 天前
使用helm在k8s集群部署MySQL单实例,支持当前所有主版本的最新子版本
mysql·adb·kubernetes