MySQL常用函数包括字符串函数、 数值函数、日期和时间函数、流程函数等。也许在Java开发中并不需要全都掌握,但是了解总比是个愣头青强吧!况且如果结合业务场景选择合适的函数来简化sql的查询处理,往往能事半功倍。
MySQL中的函数格式基本都是函数名加括号加形参组成,不只是MySQL,其他语言的函数名称构成也差不多,所以说我们在使用MySQL时,函数名括号不能省略。MySQL中的字符串函数,不用刻意去记忆,比如求子串,字符串替换等,函数的第一个操作数必定是字符串本身,其他参数就结合函数的功能去填写。
5.1 字符串函数
(1)CONCAT(s1,s2,...sn)函数:把传入的参数连接成一个字符串。任何字符串与NULL连接的结果都将是NULL。
mysql> select concat("hello"," world!");
+---------------------------+
| concat("hello"," world!") |
+---------------------------+
| hello world! |
+---------------------------+
mysql> select insert("hello world!",7,6,"mysql!");
+-------------------------------------+
| insert("hello world!",7,6,"mysql!") |
+-------------------------------------+
| hello mysql! |
+-------------------------------------+
mysql> select upper("hello mysql!");
+-----------------------+
| upper("hello mysql!") |
+-----------------------+
| HELLO MYSQL! |
+-----------------------+
mysql> select left("hello mysql!",5);
+------------------------+
| left("hello mysql!",5) |
+------------------------+
| hello |
+------------------------+
mysql> select lpad(" mysql!",12,"hello");
+----------------------------+
| lpad(" mysql!",12,"hello") |
+----------------------------+
| hello mysql! |
+----------------------------+
mysql> select ltrim(" mysql");
+------------------+
| ltrim(" mysql") |
+------------------+
| mysql |
+------------------+
mysql> select replace("hello world!","world","mysql");
+-----------------------------------------+
| replace("hello world!","world","mysql") |
+-----------------------------------------+
| hello mysql! |
+-----------------------------------------+
# 字符串的比较是按照ASCII码值进行比较的,如果第一个字符就能确定大小,则不会在往后比较
# strcmp函数:比较字符串s1和s2的ASCII码值的大小。如果s1比s2小,那么返回-1;如果s1与s2相等,那么返回0;如果s1比s2大,那么返回1
mysql> select strcmp('a','b'), strcmp('A','A'),strcmp('C','b');
+-----------------+-----------------+-----------------+
| strcmp('a','b') | strcmp('A','A') | strcmp('C','b') |
+-----------------+-----------------+-----------------+
| -1 | 0 | 1 |
+-----------------+-----------------+-----------------+
mysql> select '18'<'2';
+----------+
| '18'<'2' |
+----------+
| 1 |
+----------+
mysql> select 'abc' > '123';
+---------------+
| 'abc' > '123' |
+---------------+
| 1 |
+---------------+
mysql> select substring("hello mysql!",7,5);
+-------------------------------+
| substring("hello mysql!",7,5) |
+-------------------------------+
| mysql |
+-------------------------------+
5.2 数值函数
mysql> select abs(-0.1),abs(0.1);
+-----------+----------+
| abs(-0.1) | abs(0.1) |
+-----------+----------+
| 0.1 | 0.1 |
+-----------+----------+
mysql> select ceil(-0.8),ceil(0.8);
+------------+-----------+
| ceil(-0.8) | ceil(0.8) |
+------------+-----------+
| 0 | 1 |
+------------+-----------+
mysql> select floor(-0.8),floor(0.8);
+-------------+------------+
| floor(-0.8) | floor(0.8) |
+-------------+------------+
| -1 | 0 |
+-------------+------------+
# 模数和被模数任何一个为NULL结果都为NULL
mysql> select mod(15,10),mod(1,11),mod(NULL,10);
+------------+-----------+--------------+
| mod(15,10) | mod(1,11) | mod(NULL,10) |
+------------+-----------+--------------+
| 5 | 1 | NULL |
+------------+-----------+--------------+
# rand函数返回0-1内的随机值,边界值取不到
mysql> select RAND();
+--------------------+
| RAND() |
+--------------------+
| 0.5434079063529222 |
+--------------------+
# 产生0-100以内的随机整数
mysql> select ceil(100*rand());
+------------------+
| ceil(100*rand()) |
+------------------+
| 52 |
+------------------+
1 row in set (0.00 sec)
#round返回参数x的四舍五入的有y位小数的值,truncate不会四舍五入,仅仅截断y位小数
mysql> select round(5.125,2),truncate(5.125,2);
+----------------+-------------------+
| round(5.125,2) | truncate(5.125,2) |
+----------------+-------------------+
| 5.13 | 5.12 |
+----------------+-------------------+
5.3 日期和时间函数
#CURDATE():返回当前日期,只包含年月日
mysql> select CURDATE();
+------------+
| CURDATE() |
+------------+
| 2020-07-20 |
+------------+
#CUETIME():返回当前时间,只包含时分秒
mysql> select CURTIME();
+-----------+
| CURTIME() |
+-----------+
| 15:16:52 |
+-----------+
#NOW():返回当前的时间,年月日时分秒
mysql> select NOW();
+---------------------+
| NOW() |
+---------------------+
| 2020-07-20 15:17:03 |
+---------------------+
#UNIX_TIMESTAMP(date):返回日期date的UNIX时间戳 可通过该函数进行日期类型的比较
#FROM_UNIXTIME(unixtime):返回UNIXTIME时间戳的日期值,和UNIXTIMESTAMP(date)互为逆操作
mysql> select UNIX_TIMESTAMP(now());
+-----------------------+
| UNIX_TIMESTAMP(now()) |
+-----------------------+
| 1595229496 |
+-----------------------+
mysql> select FROM_UNIXTIME(1595229496);
+---------------------------+
| FROM_UNIXTIME(1595229496) |
+---------------------------+
| 2020-07-20 15:18:16 |
+---------------------------+
#WEEK(date)和YEAR(date)函数:前者返回所给的日期是一年中的第几周,后者返回所给的日期是哪一年
mysql> select WEEK(CURDATE()),YEAR(CURDATE());
+-----------------+-----------------+
| WEEK(CURDATE()) | YEAR(CURDATE()) |
+-----------------+-----------------+
| 29 | 2020 |
+-----------------+-----------------+
#HOUR(time)和MINUTE(time)函数:前者返回所给时间的小时,后者返回所给时间的分钟。
mysql> select HOUR(CURTIME()),MINUTE(CURTIME());
+-----------------+-------------------+
| HOUR(CURTIME()) | MINUTE(CURTIME()) |
+-----------------+-------------------+
| 15 | 27 |
+-----------------+-------------------+
#MONTHNAME(date):返回date的英文月份名称
mysql> select MONTHNAME(CURDATE());
+----------------------+
| MONTHNAME(CURDATE()) |
+----------------------+
| July |
+----------------------+
#【了解】
#DATE_FORMAT(date,fmt):按字符串fmt格式化日期值,MySQL中的日期时间格式如表5-4
#DATE_ADD(date,INTERVAL expr type):返回与所给日期date相差INTERVAL时间段的日期。INTERVAL是间隔类型关键字,expr是一个表达式,type表示间隔类型,type间隔类型如表5-5
#DATEDIFF(date1,date2):用来计算两个日期之间相差的天数
mysql> select DATE_FORMAT(NOW(),"%Y %M %D");
+-------------------------------+
| DATE_FORMAT(NOW(),"%Y %M %D") |
+-------------------------------+
| 2020 July 20th |
+-------------------------------+
mysql> select now() current,date_add(now(),INTERVAL 31 day) after31days,date_add(now(),INTERVAL '1_2' year_month) after_oneyear_twomonth;
+---------------------+---------------------+------------------------+
| current | after31days | after_oneyear_twomonth |
+---------------------+---------------------+------------------------+
| 2020-07-20 15:41:56 | 2020-08-20 15:41:56 | 2021-09-20 15:41:56 |
+---------------------+---------------------+------------------------+
1 row in set (0.00 sec)
# 可以用负数让它返回之前的某个日期时间
mysql> select now() current,date_add(now(),INTERVAL -31 day) before31days,date_add(now(),INTERVAL '-1_-2' year_month) before_oneyear_twomonth;
+---------------------+---------------------+-------------------------+
| current | before31days | before_oneyear_twomonth |
+---------------------+---------------------+-------------------------+
| 2020-07-20 15:42:04 | 2020-06-19 15:42:04 | 2019-05-20 15:42:04 |
+---------------------+---------------------+-------------------------+
1 row in set (0.00 sec)
# 距离新年还有多少天 希望再次看到的话,努力没有白费!
mysql> select DATEDIFF('2021-01-01',CURDATE());
+----------------------------------+
| DATEDIFF('2021-01-01',CURDATE()) |
+----------------------------------+
| 165 |
+----------------------------------+
什么是时间戳?
时间戳是指格林威治时间1970年01月01日00时00分00秒(北京du时间1970年01月01日08时00分00秒)起至现在的总秒数。通俗的讲, 时间戳是一份能够表示一份数据在一个特定时间点已经存在的完整的可验证的数据。
5.4 流程函数
下面以模拟对职员薪水进行分类为例:
mysql> create table salary(userid int,salary decimal(9,2));
mysql> insert into salary values(1,100),(2,2000),(3,3000),(4,4000),(5,5000),(1,NULL);
mysql> select * from salary;
+--------+---------+
| userid | salary |
+--------+---------+
| 1 | 1000.00 |
| 2 | 2000.00 |
| 3 | 3000.00 |
| 4 | 4000.00 |
| 5 | 5000.00 |
| 1 | NULL |
+--------+---------+
# 月薪在2000元以上的职员用“high”表示
mysql> select if(salary>2000,'high','low') from salary;
+------------------------------+
| if(salary>2000,'high','low') |
+------------------------------+
| low |
| low |
| high |
| high |
| high |
| low |
+------------------------------+
6 rows in set (0.00 sec)
# NULL值不能参与数值运算,下面将NULL值替换
mysql> select ifnull(salary,0) from salary;
+------------------+
| ifnull(salary,0) |
+------------------+
| 1000.00 |
| 2000.00 |
| 3000.00 |
| 4000.00 |
| 5000.00 |
| 0.00 |
+------------------+
6 rows in set (0.00 sec)
mysql> select case when salary<=2000 then 'low' else 'high' end from salary;
+---------------------------------------------------+
| case when salary<=2000 then 'low' else 'high' end |
+---------------------------------------------------+
| low |
| low |
| high |
| high |
| high |
| high |
+---------------------------------------------------+
6 rows in set (0.00 sec)
# 多个when...then联合使用
mysql> select case salary when 1000 then 'low' when 2000 then 'mid' else 'high' end from salary;
+-----------------------------------------------------------------------+
| case salary when 1000 then 'low' when 2000 then 'mid' else 'high' end |
+-----------------------------------------------------------------------+
| low |
| mid |
| high |
| high |
| high |
| high |
+-----------------------------------------------------------------------+
5.5 其他常用函数
示例:
# 查看当前操作数据库
mysql> select database();
+------------+
| database() |
+------------+
| test |
+------------+
# 查看mysql版本
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.26 |
+-----------+
# 查看当前用户
mysql> select user();
+----------------+
| user() |
+----------------+
| root@localhost |
+----------------+
#INET_ATON(IP):返回IP地址的网络字节序表示
mysql> select inet_aton('192.168.8.1');
+--------------------------+
| inet_aton('192.168.8.1') |
+--------------------------+
| 3232237569 |
+--------------------------+
#INET_NTOA(num):返回网络字节序代表的IP地址
mysql> select inet_ntoa(3232237569);
+-----------------------+
| inet_ntoa(3232237569) |
+-----------------------+
| 192.168.8.1 |
+-----------------------+
INET_ATON(IP)和INET_NTOA(num)函数的主要用途是将字符串的IP地址转换为数字表示的网络字节序,这样可以很方便地进行IP或者网段的比较。比如在下面的表t中,要想知道在192.168.1.3-192.168.1.20 一共有多少个IP地址:
mysql> select * from t;
+--------------+
| ip |
+--------------+
| 192.168.1.1 |
| 192.168.1.3 |
| 192.168.1.6 |
| 192.168.1.10 |
| 192.168.1.20 |
| 192.168.1.30 |
+--------------+
#正常思维来想的话,肯定是字符串比较,但是不出乎意料,结果为空。字符串比较是一个一个字符比较的,当对应字符相同时候,比较下一个,知道遇到能区分大小的字符,就停止比较,后面的字符也将忽略。因为字符"3"比“2”大,而不能用我们日常的思维3<20,所以比“3”大比“2”小的结果为空。
mysql> select * from t where ip>='192.168.1.3' and ip<='192.168.1.20';
# 要想实现上面的功能,就可用INET_ATON函数将IP转化为字节序后在比较,如下所示:
mysql> select * from t where inet_aton(ip)>=inet_aton('192.168.1.3')&&inet_aton(ip)<=inet_aton('192.168.1.20');
+--------------+
| ip |
+--------------+
| 192.168.1.3 |
| 192.168.1.6 |
| 192.168.1.10 |
| 192.168.1.20 |
+--------------+