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。

相关推荐
游戏开发爱好者83 小时前
网络连接排查指南,谁在电脑后台偷跑流量,哪些程序在联网
网络协议·计算机网络·网络安全·ios·adb·https·udp
实心儿儿3 小时前
MySQL 的安装
数据库·mysql·adb
2601_962300478 小时前
基于Python与Tkinter的ADB Monkey自动化测试脚本开发
python·adb·tkinter·android测试·gui自动化
flower_drop2 天前
基于 WebUSB 与 CDP:在浏览器端实现 Android 设备通信与无证书抓包实践
android·chrome·测试工具·adb·bug·edge浏览器
蜡台3 天前
# 已解决|MySQL 8\.4\.11 密码正确仍报错1045 \(28000\) Access denied 终极修复方案
android·mysql·adb
leoZ2313 天前
2026-09-08-mysql-57-init-walkthrough
前端·javascript·数据库·vue.js·opencv·mysql·adb
2501_915921433 天前
抓包工具对比:Charles、TraceEagle、Wireshark、Fiddler 与 Proxyman
网络协议·计算机网络·网络安全·ios·adb·https·udp
秋不溜啾3 天前
三星手机网络连接ADB和关闭自动更新
adb·安卓
没文化的阿浩3 天前
【MySQL】用户管理
android·mysql·adb
Michaelwubo3 天前
mysql8 主从 HA切换
android·adb