1.MySQL的内置函数
1.1日期函数
| 函数名称 | 描述 | 示例 |
|---|---|---|
current_date() |
获取当前系统日期(格式:YYYY-MM-DD) |
SELECT current_date(); → 2026-05-23 |
current_time() |
获取当前系统时间(格式:HH:MM:SS) |
SELECT current_time(); → 15:30:45 |
current_timestamp() |
获取当前日期 + 时间(格式:YYYY-MM-DD HH:MM:SS) |
SELECT current_timestamp(); → 2026-05-23 15:30:45 |
date(datetime) |
提取 datetime 参数中的日期部分 |
SELECT date('2026-05-23 15:30:45'); → 2026-05-23 |
date_add(date, interval d_value type) |
给日期 / 时间增加指定单位的数值 | SELECT date_add('2026-05-23', interval 7 day); → 2026-05-30 |
date_sub(date, interval d_value type) |
从日期 / 时间减去指定单位的数值 | SELECT date_sub('2026-05-23', interval 1 month); → 2026-04-23 |
datediff(date1, date2) |
计算两个日期的差值,结果单位为天 | SELECT datediff('2026-06-01', '2026-05-23'); → 9 |
now() |
获取当前日期 + 时间,和 current_timestamp() 效果一致 |
SELECT now(); → 2026-05-23 15:30:45 |
interval 支持的单位 : 除了表格里提到的 year、minute、second、day,还支持 month、hour、week 等。 例如:interval 2 hour(2 小时)、interval 3 month(3 个月)。
datediff 注意事项 : 它的计算规则是 date1 - date2,结果为正数表示 date1 在 date2 之后,负数则相反。
now() vs current_timestamp() : 两者在大部分场景下完全等价,now() 更简洁,日常开发中使用频率更高。
2.字符串函数
| 函数名称 | 描述 | 示例 |
|---|---|---|
charset(str) |
返回字符串的字符集 | SELECT charset('abc'); → utf8mb4 |
concat(string2 [, ...]) |
连接多个字符串 | SELECT concat('Hello', ' ', 'World'); → Hello World |
instr(string, substring) |
返回子串在字符串中首次出现的位置(从 1 开始计数,找不到返回 0) | SELECT instr('abcdef', 'cd'); → 3 |
ucase(string2) |
将字符串全部转为大写(同 upper()) |
SELECT ucase('hello'); → HELLO |
lcase(string2) |
将字符串全部转为小写(同 lower()) |
SELECT lcase('HELLO'); → hello |
left(string2, length) |
从字符串左侧取指定长度的字符 | SELECT left('abcdef', 3); → abc |
length(string) |
返回字符串的字节长度(注意:不是字符数) | SELECT length('你好'); → 6(utf8mb4 下每个汉字占 3 字节) |
replace(str, search_str, replace_str) |
用指定字符串替换原字符串中的目标子串 | SELECT replace('abcabc', 'a', 'x'); → xbcxbc |
strcmp(string1, string2) |
逐字符比较两字符串大小,返回 - 1/0/1(小于 / 等于 / 大于) | SELECT strcmp('apple', 'banana'); → -1 |
substring(str, position [, length]) |
从指定位置开始,截取指定长度的子串 | SELECT substring('abcdef', 2, 3); → bcd |
ltrim(string) |
去除字符串左侧的空格 | SELECT ltrim(' abc'); → abc |
rtrim(string) |
去除字符串右侧的空格 | SELECT rtrim('abc '); → abc |
trim(string) |
去除字符串两侧的空格 | SELECT trim(' abc '); → abc |
**charset (str)**返回字符串的字符集信息,例如 utf8mb4、gbk 等,常用于排查乱码问题。 该函数仅返回元数据,不改变原字符串内容。
**concat ()**支持多个参数拼接,参数类型会自动转为字符串。 若任意参数为 NULL,结果直接返回 NULL,需用 IFNULL 处理。 例如 SELECT concat (' 用户 ',IFNULL (name,' 匿名 ')) FROM user。
**instr (str,sub)**位置从 1 开始计数,找不到子串返回 0,区分大小写。 若要实现不区分大小写的查找,可配合 LOWER 或 UCASE 使用,例如 SELECT instr (LOWER (str),LOWER (sub))。
ucase () 与 lcase () ucase () 等同于 UPPER (),lcase () 等同于 LOWER (),两者可互换使用。 仅对英文字母生效,中文无大小写转换效果。
left (str,len) len 为正整数,代表截取字符数,不是字节数。 len 超过字符串长度时,返回原字符串。 若需从右侧截取,可使用 RIGHT (str,len),用法与 left 对称。
**length (str)**统计的是字节长度,受字符集影响,utf8mb4 下每个汉字占 3-4 字节。 如需统计字符数,应使用 char_length (str),不受字符集影响。 例如 SELECT length (' 你好 '),char_length (' 你好 '),结果为 6 和 2。
**replace (str,search_str,replace_str)**替换所有匹配的子串,不支持正则匹配。 若需正则替换,可使用 REGEXP_REPLACE(MySQL 8.0 及以上版本支持)。
**strcmp (str1,str2)**逐字符按 ASCII 码值比较,返回 - 1、0、1 分别表示小于、等于、大于。 仅支持字符串比较,数字会先转为字符串再比较,例如 strcmp ('10','2') 会返回 - 1,因为 '10' 的首字符 '1' 小于 '2'。
**substring (str,pos [,len])**pos 为 1 时表示从开头截取,为负数时从字符串末尾倒数计数。 省略 len 参数时,截取到字符串末尾。 也可写作 substr (str,pos [,len]),两者功能完全一致。 例如 SELECT substring ('abcd',-3,2),结果为 bc。
**ltrim ()、rtrim ()、trim ()**默认仅去除空格,也可指定去除其他字符。 trim 支持三种格式:trim (leading 'x' FROM str) 去除开头的 x,trim (trailing 'x' FROM str) 去除结尾的 x,trim (both 'x' FROM str) 去除两端的 x。 例如 SELECT trim (both 'x' FROM 'xxabcxx'),结果为 abc。
3.数字函数
| 函数名称 | 描述 | 示例 |
|---|---|---|
| abs(number) | 求绝对值 | SELECT abs(-10) |
| bin(decimal_number) | 十进制转二进制 | SELECT bin(10) |
| hex(decimalNumber) | 十进制转十六进制 | SELECT hex(10) |
| conv(number,from_base,to_base) | 任意进制转换 | SELECT conv(10,10,2) |
| ceiling(number) | 向上取整 | SELECT ceiling(3.2) |
| floor(number) | 向下取整 | SELECT floor(3.8) |
| format(number,decimal_places) | 数字格式化 | SELECT format(1234.567,2) |
| rand() | 生成随机数 | SELECT rand() |
| mod(number,denominator) | 取余数 | SELECT mod(10,3) |
abs 返回数值的绝对值,整数小数都支持 输入 null 结果为 null。bin 把十进制数字转成二进制字符串 小数会自动截断成整数 等价写法 conv (数字,10,2)。hex 十进制转十六进制 也可以把字符串转成十六进制编码。conv 支持 2-36 任意进制互相转换 第一个参数是待转换数 第二个是原进制 第三个是目标进制。ceiling 向上取整,别名 ceil 正数小数直接进一 负数小数往 0 方向取整。floor 向下取整 正数直接舍去小数 负数往负无穷方向取整。format 格式化数字,自动加千分位 四舍五入保留指定位数 结果是字符串,不能直接计算。rand 返回 0 到 1 之间的随机小数 固定种子会生成固定随机数。mod取模运算,等价于 % 结果符号和被除数一致。
1.4其他函数
| 函数名称 | 描述 | 示例 |
|---|---|---|
| user() | 查询当前登录用户 | select user(); |
| md5(str) | 字符串 MD5 加密,返回 32 位字符串 | select md5('admin'); |
| database() | 显示当前使用的数据库 | select database(); |
| password() | MySQL 用户密码加密 | select password('root'); |
| ifnull(val1,val2) | val1 为 null 返回 val2,否则返回 val1 | select ifnull(null,'123'); |
user () 返回当前登录 MySQL 的账号和主机地址 格式为 用户名 @主机名。md5 (str) 固定生成 32 位长度的加密字符串 不可逆加密,常用于简单密码验证 相同字符串每次加密结果一致。database () 返回当前正在使用的数据库名称 没有选择数据库时返回 null 使用 use 数据库名 后可正常显示。password () MySQL 系统专用的密码加密函数 生成以 * 开头的 41 位字符串 MySQL 8.0 版本已不推荐使用。ifnull (val1,val2) 专门处理 null 值的判断函数 只有两个参数,必须成对使用 val2 可以是数字、字符串、字段名 常用在查询结果中替换 null 为默认值。
2.复合查询
2.1多表查询
多表查询就是在支持的select语句的from后加多个表而言,注意表名之间用逗号隔开。查询的行要注意表之间是否重复,如果重复要表明是哪个表的行。
Create Table: CREATE TABLE `EMP` (
`EMPNO` int NOT NULL COMMENT '员工编号',
`ENAME` varchar(20) DEFAULT NULL COMMENT '员工姓名',
`JOB` varchar(20) DEFAULT NULL COMMENT '职位',
`MGR` int DEFAULT NULL COMMENT '上级编号',
`HIREDATE` date DEFAULT NULL COMMENT '入职日期',
`SAL` decimal(7,2) DEFAULT NULL COMMENT '月薪',
`COMM` decimal(7,2) DEFAULT NULL COMMENT '奖金',
`DEPTNO` int DEFAULT NULL COMMENT '部门编号',
PRIMARY KEY (`EMPNO`),
KEY `DEPTNO` (`DEPTNO`),
CONSTRAINT `EMP_ibfk_1` FOREIGN KEY (`DEPTNO`) REFERENCES `DEPT` (`DEPTNO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
显示部门号为10的部门名,员工名和工资
select ename, sal,dname from EMP, DEPT where EMP.deptno=DEPT.deptno and
DEPT.deptno = 10;
显示各个员工的姓名,工资,及工资级别
select ename, sal, grade from EMP, SALGRADE where EMP.sal between losal and
hisal;
2.2自链接
自连接是指在同一张表连接查询。
//显示员工 FORD 的上级领导的编号和姓名(mgr 是员工领导的编号 --empno)使用子查询
select empno,ename from emp where emp.empno=(select mgr from emp where ename='FORD');
//使用多表查询(自连接)
-- 使用到表的别名
-- from emp leader, emp worker,给自己的表起别名,因为要先做笛卡尔积,所以别名可以先识别
select leader.empno,leader.ename from emp leader, emp worker where leader.empno = worker.mgr and worker.ename='FORD';
2.3子查询
子查询是指嵌套在其他select语句的select语句,也叫嵌套查询。
2.3.1单行查询
返回一行记录的子查询。
显示 SMITH 同一部门的员工
select * from EMP where deptno=(select deptno from EMP where ename='SMITH');
2.3.2多行子查询
返回多行记录的子查询。可以使用关键字:in: 在多个结果里匹配任意一个 就满足条件 子查询返回多行时用 例子:岗位是 10 部门里任意一种就行。all: 必须大于 / 小于所有结果 比全部都高 / 都低才满足 例子:工资比 30 部门所有人都高。any: 满足大于 / 小于任意一个结果 比其中一个高 / 低就行 例子:工资比 30 部门任意一个人高
2.4合并查询
合并查询用于把多个 select 结果合在一起 ,用两个关键字:union 、union all。
union :功能:合并两个结果集,自动去掉重复行 适用场景:既要合并,又要去重。
案例:找出工资 > 2500 或者 职位是 MANAGER 的人。
select ename,sal,job from EMP where sal>2500
union
select ename,sal,job from EMP where job='MANAGER';
union all :功能:合并两个结果集,不去重,保留所有记录 。适用场景:只合并,不做去重,效率更高 。
案例:同上,不去重。
select ename,sal,job from EMP where sal>2500
union all
select ename,sal,job from EMP where job='MANAGER';
两个关键字区别:union:合并 + 去重 + 排序 union all:只合并,不去重,执行更快。
-- 高于部门平均工资
select ename,deptno,sal,format(asal,2) from EMP,
(select avg(sal) asal,deptno dt from EMP group by deptno) tmp
where EMP.sal>tmp.asal and EMP.deptno=tmp.dt;
-- 各部门最高工资
select EMP.ename,EMP.sal,EMP.deptno,ms from EMP,
(select max(sal) ms,deptno from EMP group by deptno) tmp
where EMP.deptno=tmp.deptno and EMP.sal=tmp.ms;
-- 部门人数统计
select DEPT.deptno,dname,mycnt,loc from DEPT,
(select count(*) mycnt,deptno from EMP group by deptno) tmp
where DEPT.deptno=tmp.deptno;