Go to comments

兄弟连 Mysql 内置系统函数

查询语句或插入语句的时候,往往能会用的 mysql 系统内置的函数,

丰富的函数使工作事半功倍,帮助我们做很多事情,比如字符串的处理,数值的运算,日期的运算等等,帮助开发人员编写简单快捷的 sql 语句


什么是内置函数?

这些函数可以用在 SELECT 语句,及它的子句 where、order by、having 等等 

也可以用在 UPDATE、DELETE 这些语句以及它们的子句中


其中 Mysql 中常用的内置函数有

1. 字符串函数、2. 数值函数、3. 日期函数、还有之前的统计函数...


一、字符串函数

基本上 PHP 中用的字符串函数,大部分在 Mysql 中也提供了,

可以打开 Mysql 手册,左侧栏找到“函数和操作符”,可以看到字符串函数、数值函数、日期函...


常用的一些字符串函数

函数作用
concat(str1, str2...strn)把传入的参数链接成一个字符串
insert(str, x, y, insert)将字符串 str,从 x 的位置开始,y 个字符串长度替换为 字符串" insert"
lower(str)将传入的字符串转成小写
upper(str)将传入的字符串转成大写


left(str, x)返回字符串最左边的 x 字符,

返回字符串最右边的 x 字符

如果第二个参数传 null,则返回 null

right(str, x)


lpad(str, n, pad) l 是 left 的缩写

用字符串 pad,对字符串 str 最左边或最右边进行填充,直到长度为 n 个字符长度为止

rpad(str, n, pad) r 是 rigth 的缩写


trim(str)去掉字符串两边空格
ltrim(str)去左边空格
rtrim(str)去掉右边的空格


replace(str, a, b);用字符串 b 替换字符串 str 中所有出现的字符串 a


strcmp(str1, str2)比较函数是按 ACSII 码字节比较的,比较 str1 和 str2 的 ACSII 码值的大小
如果 str1 比 str2 小返回 -1
如果 str1 比str2 大返回 1
如果 str1 等于 str2 小返回 0


substr(str, x, y)返回字符串 str 中第 x 的位置开始,y 个字符串长度


concat()  字符串链接


将字符串 'abc' 链接 'cfg'

select concat('abc', 'efg');

+----------------------+

 | concat('abc', 'efg')   |

+----------------------+

 | abcefg                     | 两个字符串连接了

+----------------------+


在链接第三个字符串 "kil"

select concat('abc', 'efg', "kil");

+-----------------------------+

 | concat('abc', 'efg', "kil")     |

+-----------------------------+

 | abcefgkil                            |

+-----------------------------+


在链接第四个 "hello"

select concat('abc', 'efg', "kil", "hello");

+--------------------------------------+

 | concat('abc', 'efg', "kil", "hello")     |

+--------------------------------------+

 | abcefgkilhello                                 |    在 select 语句中用 concat() 函数里,把所有的参数链接在一起

+--------------------------------------+


也可以在 concat() 函数里面直接用变量,对于表来说“列”就是变量,

比如创建一个 user 用户表,并插入两条数据

create table users(
  id int,
  name char(30),
  age tinyint
);

insert into users values(1, '张三', 40),(2, '李四', 39);

select * from users;

+------+------+------+

 | id      | name| age   |

+------+------+------+

 |    1    | 张三   |   40   |

 |    2    | 李四   |   39   |

+------+------+------+


上面 concat() 函数里面写的是字符串,

如果直接里写的是字段名 concat(name, age)  那么变量的值就是这个列对应的记录

select concat(name, "年龄是:", age) from users;

+-------------------------------+

 | concat(name, "年龄是:", age) |

+-------------------------------+

 | 张三年龄是:40                     |

 | 李四年龄是:39                     |

+-------------------------------+


对于数据表字段就是变量(variables)

select concat(name, '的年龄是', age) from users;

函数中可以将列(字段)作为变量来用,变量的值就是这个列对应的每一行记录

也可以在 where 字句中和 order by 字句中用等


insert( str, x, y, insert )  替换


作用将字符串 str,从 x 开始的位置,y 个字符串长度的字符替换为 insert

select insert("abcdefg", 2, 3, 'hellow');

从第 2 个 b 开始(从 1 开始计数,1 是 a),

往后 3 个长度的字符 bcd

换成 "hellow"

+-----------------------------------+

 | insert("abcdefg", 2, 3, 'hellow')  |

+-----------------------------------+

 | ahellowefg                                 |

+-----------------------------------+


修改一下表的内容

update users set name = '张三大兄弟' where id = 1;

update users set name = '李四大兄弟' where id = 2;

select * from users;

+------+------------+------+

 | id      | name         | age   |

+------+------------+------+

 |    1    | 张三大兄弟 |   40   |

 |    2    | 李四大兄弟 |   39   |

+------+------------+------+


中文字符也是可以替换,

将名字的第 3 个字符后面的 3 个字符换成“是中国人

select insert(name, 3, 3, "是中国人") from users;

 "张三兄弟" 这三个字符换了

第3个字符是字,网红3个是兄弟,然后替换为“是中国人”

+--------------------------------+

 | insert(name, 3, 3, "是中国人") |

+--------------------------------+

 | 张三是中国人                           |

 | 李四是中国人                           |

+--------------------------------+


对比原来没有换的名字

select insert(name, 3, 3, "是中国人"), name from users;

+--------------------------------+------------+

 | insert(name, 3, 3, "是中国人") | name         |

+--------------------------------+------------+

 | 张三是中国人                           | 张三大兄弟 |

 | 李四是中国人                           | 李四大兄弟 |

+--------------------------------+------------+


lower()   将字符串转成小写

upper()   将字符串转成大写

select lower("HELLO"), upper('hello');

+----------------+----------------+

 | lower("HELLO") | upper('hello') |

+----------------+----------------+

 | hello                | HELLO             |

+----------------+----------------+


插入 name 字段小写英文 monica

insert into users values(3, 'maria', 37);

select * from users;

+------+------------+------+

 | id      | name         | age   |

+------+------------+------+

 |    1    | 张三大兄弟 |   40   |

 |    2    | 李四大兄弟 |   39   |

 |    3    | maria        |   37   |

+------+------------+------+


查询 name 字段等于 maria 的,将名字转成大写的 MARIA 在等于大写的 MARIA

select * from users where upper(name) = 'MARIA';

不管 maria 大写还是小写,查询时候都换成大写的就查询出来了

+------+--------+------+

 | id      | name   | age    |

+------+--------+------+

 |    3    | maria    |   37   |

+------+--------+------+


left( str, x )

right( str, x )

截取


返回字符串最左边和最右边的 x 个字符,如果第二个参数为 null 空,则不返回任何字符

select left('abcdefg', 3), right('abcdefg', 3);

+--------------------+---------------------+

 | left('abcdefg', 3)   | right('abcdefg', 3)   |

+--------------------+---------------------+

 | abc                        | efg                          |

+--------------------+---------------------+


如果第二个参数 x 传的是空 null,则返回的就是 null

select left('abcdefg', 3), right('abcdefg', 3), left('abcdefg', null);

+--------------------+---------------------+-----------------------+

 | left('abcdefg', 3)    | right('abcdefg', 3)  | left('abcdefg', null)    |

+--------------------+---------------------+-----------------------+

 | abc                        | efg                          | NULL                         |

+--------------------+---------------------+-----------------------+


lpad( str, n, pad )   l 是 left 的缩写

rpad( str, n, pad )   r 是 rigth 的缩写

用字符串 pad 对 str 最左边和最右边进行填充,直到个长度为 n 个字符长度为止


查看 users 表

select name from users;

+------------+

 | name         |

+------------+

 | 张三大兄弟 |

 | 李四大兄弟 |

 | maria         |

+------------+


比如把 name 字段都补足 10 个字符的长度

左边用 # 号补充

右边用 @ 号补充

select lpad(name, 10, '*'), rpad(name, 10, '@') from users;

+---------------------+---------------------+

 | lpad(name, 10, '*')  | rpad(name, 10, '@') |

+---------------------+---------------------+

 | *****张三大兄弟      | 张三大兄弟@@@@@ |

 | *****李四大兄弟      | 李四大兄弟@@@@@ |

 | *****maria              | maria@@@@@        |

+---------------------+---------------------+


trim(str)    去掉字符串两边空格

ltrim(str)   去左边空格

rtrim(str)   去掉右边的空格

select trim("   abc   "), ltrim("   abc   "), rtrim("   abc   ");

这样有点看不出来

+-------------------+--------------------+--------------------+

 | trim("   abc   ")    | ltrim("   abc   ")      | rtrim("   abc   ")     |

+-------------------+--------------------+--------------------+

 | abc                      | abc                        |    abc                     |

+-------------------+--------------------+--------------------+


函数 concat() 在两边链接 # 在查询,

使用 \G 立起来查看,不然字段名称太长了

select concat("#", trim("   abc   "), "#"), concat("#", ltrim("   abc   "), "#"), concat("#", rtrim("   abc   "), "#") \G

*************************** 1. row ***************************

concat("#", trim("   abc   "), "#"): #abc#

concat("#", ltrim("   abc   "), "#"): #abc   #

concat("#", rtrim("   abc   "), "#"): #   abc#


给字段起一个别名,看的更清晰

select concat("#", trim("   abc   "), "#") one, concat("#", ltrim("   abc   "), "#") two, concat("#", rtrim("   abc   "), "#") three;

+-------+----------+----------+

 | one    | two         | three       |

+-------+----------+----------+

 | #abc# | #abc   # | #   abc#  |

+-------+----------+----------+


replace( str, a, b )

将字符串 str 中所有 "a" 都替换成 "-"

select replace("希望a世界更好a所有的不如意a都消散", "a", " - ");

+----------------------------------------------------------+

 | replace("希望a世界更好a所有的不如意a都消散", "a", " - ") |

+----------------------------------------------------------+

 | 希望 - 世界更好 - 所有的不如意 - 都消散                        |

+----------------------------------------------------------+


strcmp(str1, str2)

字符串比较函数,是按 ACSII 码字节比较的


比较的是字符串 str1 和 str2 它们 ACSII 码的大小

如果 str1 比 str2 小,则返回  -1

如果 str1 比 str2 大,则返回  1

如果 str1 等于 str2 ,则返回  0

select strcmp("a", "b"), strcmp("b", "a"), strcmp("a", "a");

+------------------+------------------+------------------+

 | strcmp("a", "b") | strcmp("b", "a")  | strcmp("a", "a")  |

+------------------+------------------+------------------+

 |               -1         |                1          |                0          |

+------------------+------------------+------------------+


substr(str, 3, 9) 


截取字符串,从第 3 个字符截取,截取 9 个字符

select substr("学习Mysql,学习了两三部教程后,感觉入门了", 3, 9);

+-----------------------------------------------------------+

 | substr("学习Mysql,学习了两三部教程后,感觉入门了", 3, 9) |

+-----------------------------------------------------------+

 | Mysql,学习了                                                               |

+-----------------------------------------------------------+


二、数值函数

mysql 数值函数能处理很多数值方面的运算问题

函数作用
abs(x)返回 x 的绝对值
ceil(x)

返回大于 x 的最小整数,

比如 2.1、2.5、2.9 返回的都是 3,进 1 取整法
floor(x)返回小于 x 的最大整数,
比如 2.1、2.5、2.9 返回的都是 2,割舍法
mod(x, y)返回 x / y 的模(就是余数)
rand()返回 0~1 之间的随机数
round(x, y)

四舍五入函数,

返回参数 x 的四舍五入,有 y 位小数的值

truncate(x, y)

截断的函数,

返回数字 x,截断为 y 位小数的结果


abs()

返回绝对值

select abs(10), abs(-10);

正数 10 的绝对值本身就是 10

负数 10 返回的是直接去掉负号的绝对值

+---------+----------+

 | abs(10) | abs(-10)   |

+---------+----------+

 |      10    |       10      |

+---------+----------+


比如年龄取一个正数(当然年龄没有负数

select abs(age) from users;

+----------+

 | abs(age) |

+----------+

 |       40    |

 |       39    |

 |       37    |

+----------+


ceil()     向上取整

floor()   向下取整


对比一下

ceil 返回的是进 1 取整法

floor 是割舍取整法

select ceil(2.1), ceil(2.5), ceil(2.9), floor(2.1), floor(2.5), floor(2.9);

+-----------+-----------+-----------+------------+------------+------------+

 | ceil(2.1)    | ceil(2.5)    | ceil(2.9)    | floor(2.1)    | floor(2.5)   | floor(2.9)   |

+-----------+-----------+-----------+------------+------------+------------+

 |         3      |         3       |         3      |          2        |          2       |          2       |

+-----------+-----------+-----------+------------+------------+------------+


mod()

求模函数


10 % 4 模的结果是 2

select mod(10, 4);

+------------+

 | mod(10, 4) |

+------------+

 |          2       |

+------------+


10 % 5 模的结果是 0

select mod(10, 5);

+------------+

 | mod(10, 5)|

+------------+

 |          0       |

+------------+


如果前面的数小

1 % 11 模的结果是 1

select mod(1, 11);

+------------+

 | mod(1, 11)|

+------------+

 |          1      |

+------------+


如果前面是 null,返回结果也是空

select mod(null, 11);

+---------------+

 | mod(null, 11) |

+---------------+

 |          NULL    |

+---------------+


rand()

随机数函数


返回 0 ~ 1 之间的随机数,是浮动数的随机,每次的值都是不一样的

select rand();

+--------------------+

 | rand()                    |

+--------------------+

 | 0.9642467442566964 |

+--------------------+


想要 1 ~ 100 之间的随机数怎么办呢?

1. rend() 乘以 100

2. 在用 ceil 或 floor 取整

select ceil(rand()*100);

+------------------+

 | ceil(rand()*100)  |

+------------------+

 |               33         |

+------------------+


round(x, y)

四舍五入函数,返回参数 x 的四舍五入,有 y 位小数的值


不加第二个参数 y,浮点数 1.1 四舍五入返回 1

select round(1.1);

+------------+

 | round(1.1) |

+------------+

 |          1      |

+------------+


1.5 四舍五入返回 2

select round(1.5);

+------------+

 | round(1.5) |

+------------+

 |          2       |

+------------+


1.4  四舍五入返回 1

select round(1.4);

+------------+

 | round(1.4) |

+------------+

 |          1       |

+------------+


把第二个参数加上

浮点数 1.489 第二个参数是 2,返回 1.49 小数点后是 2 位的

select round(1.489, 2);

+-----------------+

 | round(1.489, 2) |

+-----------------+

 |            1.49       |

+-----------------+


truncate(x, y) 

截断函数,返回数字 x,截断为 y 位小数的结果


参数数一 12.35

参数数二 2

truncate() 函数和 round() 四舍五入函数的对比

select truncate(1.235, 2), round(1.235, 2);

truncate()  小数超过两位直接截断返回 1.23

round()  也是截断,如果后面的数超过 5 或是 5 就进一位返回 1.24

+--------------------+-----------------+

 | truncate(1.235, 2) | round(1.235, 2) |

+--------------------+-----------------+

 |               1.23         |            1.24       |

+--------------------+-----------------+


三、日期函数

有时候会遇到这样的需求

当前时间是多少?

下个月的今天是星期几?

统计截止到当前日期前三天的收入总和等等……


这些需求都需要时间日期函数来实现,

当然我们可以用 PHP 的时间戳来完成,时间戳是秒数,比如三天前怎么办呢,用当前时间戳减去 3 天的秒数就是三天前


mysql 数据库的时间日期函数

函数作用
curdate()返回当前的日期
curtime()返回当前的时间
now()返回当前日期时间
unix_timestamp(now())返回unix时间戳
from_unixtime(1632130879)返回unix时间戳日期的值
week(now())通过时间返回当前的周,一年的第几周
year(now())通过时间返回的的年
hour(now())通过时间返回当前的小时
minute(now())
date_format(now(), "%Y-%m-%d %H:%i:%s")格式化日期时间


curdate()

返回当前的日期

select curdate();

+------------+

 | curdate()   |

+------------+

 | 2021-09-20|

+------------+


curtime()

返回当前的时间

select curtime();

+-----------+

 | curtime()  |

+-----------+

 | 17:16:47   |

+-----------+


now()

现在的时间,返回既有日期又有时间

select now();

+---------------------+

 | now()                      |

+---------------------+

 | 2021-09-20 17:39:50 |

+---------------------+


unix_timestamp()

返回 unix 时间戳,比如根据当前的时间返回 unix 时间戳

select unix_timestamp(now());

+-----------------------+

 | unix_timestamp(now()) |

+-----------------------+

 |            1632130879   |  这是从 1971年 1 月 1 日 0 时 0 分 0 秒 到当前的秒数,也就是计算机元年到现在的秒数

+-----------------------+


from_unixtime()

返回 unix 时间戳对应的日期时间

select from_unixtime(1632130879);

+---------------------------+

 | from_unixtime(1632130879) |

+---------------------------+

 | 2021-09-20 17:41:19       |   返回的是时间戳 1632130879 对应的日期时间

+---------------------------+


week()

year()

hour()

从当前时间戳里面返回周、年、小时(从当前时间 now() 里返回

select week(now()), year(now()), hour(now());

+-------------+-------------+-------------+

 | week(now()) | year(now()) | hour(now()) |

+-------------+-------------+-------------+

 |          38       |        2021    |          18      |

+-------------+-------------+-------------+


hour()

minute()

second()

上面的 curtime() 是当前时间,从当前时间里面获取当前的小时、分钟、秒

select hour(curtime()) '小时', minute(curtime()) '分钟', second(curtime()) '秒';

+------+------+------+

 | 小时  | 分钟   | 秒     |

+------+------+------+

 |   15   |   23   |   25   |

+------+------+------+


monthname()

从现在日期 now() 中返回当前英文的月份

select monthname(now());

+------------------+

 | monthname(now()) |

+------------------+

 | September        |

+------------------+


date_format()

自定义的日期格式,将当前的日期 now() 格式化

select date_format(now(), "%Y-%m-%d %H:%i:%s");

+-----------------------------------------+

 | date_format(now(), "%Y-%m-%d %H:%i:%s") |

+-----------------------------------------+

 | 2021-09-20 18:12:02                           |

+-----------------------------------------+


四、流程控制函数

流程控制函数也是很常用到的一类函数,

用户可以使用这类函数,在一个 sql 语句中实现条件选择,这样就能做到提高 sql 语句的效率


先创建一个薪水的表

create table salary(
  id int not null,
  salary decimal(9, 2)
);

insert into salary values(1, 1000),(2, 2000),(3, 3000),(4, 4000),(5, 5000),(6, null);

select id, salary from salary;

+----+---------+

 | id   | salary    |

+----+---------+ 

 |  1   | 1000.00 |

 |  2   | 2000.00 |

 |  3   | 3000.00 |

 |  4   | 4000.00 |

 |  5   | 5000.00 |

 |  6   |    NULL  |

+----+---------+


一些流程控制函数(流程控制函数还有很多)

函数名作用
if(value, t, f)如果 value 值是真返回 t,如果是假返回 f
ifnull(value1, value2)如果 value1 不为空就返回 value1,否则返回 value2
case when [value1] then [result1]...else[default] end

跟程序里的 switch case 一样,

意思是如果 value1 是真返回 result1,否则返回缺省值 default


if(value, t, f)

月薪在 3000 元以上的用 hight 表示,2000 以下的用 low 表示

select id, salary, if(salary > 3000, 'hight', 'low') from salary;

+----+---------+-----------------------------------+

 | id   | salary    | if(salary > 3000, 'hight', 'low')     |

+----+---------+-----------------------------------+

 |  1   | 1000.00 | low                                              |

 |  2   | 2000.00 | low                                              |

 |  3   | 3000.00 | low                                              |

 |  4   | 4000.00 | hight                                           |

 |  5   | 5000.00 | hight                                           |

 |  6   |    NULL  | low                                              |

+----+---------+-----------------------------------+


ifnull( value1, value2 )

如果薪水不为空 null 就返回薪水,如果薪水为空就返回 0

select id, salary, ifnull(salary, 0) from salary;

+----+---------+-------------------+

 | id   | salary    | ifnull(salary, 0)      |

+----+---------+-------------------+

 |  1   | 1000.00 |           1000.00      |

 |  2   | 2000.00 |           2000.00      |

 |  3   | 3000.00 |           3000.00      |

 |  4   | 4000.00 |           4000.00      |

 |  5   | 5000.00 |           5000.00      |

 |  6   |    NULL  |              0.00         |

+----+---------+-------------------+

这个函数是替换空 null 值的,

因为 null 值是不能参与数值运算的,所以可以通过这个函数把 null 值转为 0 来代替


case when [value1] then [result1]...else[default] end

select case when salary<=3000 then '薪水小于等于三千' else '高薪水' end from salary;

+------------------------------------------------------------------+

 | case when salary<=3000 then '薪水小于等于三千' else '高薪水' end |

+------------------------------------------------------------------+

 | 薪水小于等于三千                                                                     |

 | 薪水小于等于三千                                                                     |

 | 薪水小于等于三千                                                                     |

 | 高薪水                                                                                      |

 | 高薪水                                                                                      |

 | 高薪水                                                                                      |

+------------------------------------------------------------------+


五、其它函数

其它的一些函数

函数名用途
database()当前的数据库名
version()当前 Mysql 的版本
user()当前的数据库用户
inet_aton(ip)返回 ip 的数字表示
inet_ntoa()
md5()


查看当前的数据库名(其实 \s 看状态也可以

select database();

+------------+

 | database() |

+------------+

 | dbshop     |

+------------+


查看当前的数据库版本

select version();

+------------------+

 | version()             |

+------------------+

 | 5.7.18-cynos-log|

+------------------+


查看当前登录的用户

select user();

+------------------+

 | user()                  |

+------------------+

 | root@localhost  | root 用户在本地登录的

+------------------+


返回 ip 地址的网络字节顺序

select inet_aton("192.168.1.1");

+--------------------------+

 | inet_aton("192.168.1.1")|

+--------------------------+

 |               3232235777    |

+--------------------------+


返回网络字节序列 3232235777 代表的 ip 地址

select inet_ntoa(3232235777);

+-----------------------+

 | inet_ntoa(3232235777)|

+-----------------------+

 | 192.168.1.1               |

+-----------------------+


inet_ntoa() 与 inet_aton() 是互逆的,

inet_aton() 主要用途是将字符串的 ip 地址,转为数字表示网络字节顺序,这样更方便的进行 ip 地址或者网络端的比较


password(str) 将字符串加密

select password('123456');

+-------------------------------------------+

 | password('123456')                                |

+-------------------------------------------+

 | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |

+-------------------------------------------+

大概是 41 位长的字符串

其实 password() 函数是设置 Mysql 系统里面的用户密码,不要对应用的数据加密,

password() 函数是给 Mysql 本身系统用户用的,比如给 Mysql 用户设置密码就要用 password() 加密


如果应用方面加密要使用 md5() 函数,比如网站的用户密码加密

select md5('123456');

+----------------------------------+

 | md5('123456')                           |

+----------------------------------+

 | e10adc3949ba59abbe56e057f20f883e |

+----------------------------------+


查看 Mysql 本事用户表的加密方式是 passwork() 加密

select * from mysql.user;

select * from mysql.user \G



Leave a comment 0 Comments.

Leave a Reply

换一张