函数
- 4、日期和时间函数
- 4.1、获取当前日期的函数和获取当前时间的函数
- 4.2、获取当前日期和时间的函数
- 4.3、UNIX时间戳函数
- 4.4、返回UTC日期的函数和返回UTC时间的函数
- 4.5、获取月份的函数MONTH(date)和MONTHNAME(date)
- 4.6、获取星期的函数DAYNAME(d)、DAYOFWEEK(d)和WEEKDAY(d)
- 4.7、获取星期数的函数WEEK(d)和WEEKOFYEAR(d)
- 4.8、获取天数的函数DAYOFYEAR(d)和DAYOFMONTH(d)
- 4.9、获取年份、季度、小时、分钟和秒钟的函数
- 4.10、获取日期的指定值的函数EXTRACT(type FROM date)EXTRACT(type FROM date)
- 4.11、时间和秒钟转换的函数
- 4.12、计算日期和时间的函数
- 4.13、将日期和时间格式化的函数
- 5、条件判断函数
- 6、系统信息函数
- 7、其它函数
- 8、MySQL8.0新特性——加密函数
- 9、MySQL8.0新特性——窗口函数
4、日期和时间函数
日期和时间函数主要用来处理日期和时间值,一般的日期函数除了使用DATE类型的参数外,也可以使用DATETIME或者TIMESTAMP类型的参数,但会忽略这些值的时间部分。相同的,以TIME类型值为参数的函数,可以接受TIMESTAMP类型的参数,但会忽略日期部分,许多日期函数可以同时接受数字和字符串类型的两种参数。
4.1、获取当前日期的函数和获取当前时间的函数
CURDATE()和CURRENT_DATE()函数的作用相同,将当前日期按照‘YYYY-MM-DD’或YYYYMMDD格式的值返回,具体格式根据函数在字符串或是数字语境中而定。
使用日期函数获取系统当前日期,输入语句如下:
select curdate(), current_date(), curdate() + 0;
+------------+----------------+---------------+
| curdate() | current_date() | curdate() + 0 |
+------------+----------------+---------------+
| 2026-06-23 | 2026-06-23 | 20260623 |
+------------+----------------+---------------+
可以看到,两个函数作用相同,都返回了相同的系统当前日期,“CURDATE()+0”将当前日期值转换为数值型。
CURTIME()和CURRENT_TIME()函数的作用相同,将当前时间以‘HH:MM:SS’或HHMMSS的格式返回,具体格式根据函数在字符串或是数字语境中而定。
使用时间函数获取系统当前时间,输入语句如下:
select curtime(), current_time(), curtime() + 0;
+-----------+----------------+---------------+
| curtime() | current_time() | curtime() + 0 |
+-----------+----------------+---------------+
| 16:54:39 | 16:54:39 | 165439 |
+-----------+----------------+---------------+
可以看到,两个函数的作用相同,都返回了相同的系统当前时间,“CURTIME ()+0”将当前时间值转换为数值型。
4.2、获取当前日期和时间的函数
CURRENT_TIMESTAMP()、LOCALTIME()、NOW()和SYSDATE() 4个函数的作用相同,均返回当前日期和时间值,格式为‘YYYY-MM-DD HH:MM:SS’或YYYYMMDDHHMMSS,具体格式根据函数在字符串或数字语境中而定。
使用日期时间函数获取当前系统日期和时间,输入语句如下:
select current_timestamp(), localtime(), now(), sysdate();
+---------------------+---------------------+---------------------+---------------------+
| current_timestamp() | localtime() | now() | sysdate() |
+---------------------+---------------------+---------------------+---------------------+
| 2026-06-23 16:59:31 | 2026-06-23 16:59:31 | 2026-06-23 16:59:31 | 2026-06-23 16:59:31 |
+---------------------+---------------------+---------------------+---------------------+
可以看到,4个函数返回的结果是相同的。
4.3、UNIX时间戳函数
UNIX_TIMESTAMP(date)若无参数调用,则返回一个UNIX时间戳(‘1970-01-0100:00:00’GMT之后的秒数)作为无符号整数。其中,GMT(Green wich mean time)为格林尼治标准时间。若用date来调用UNIX_TIMESTAMP(),它会将参数值以‘1970-01-01 00:00:00’GMT后的秒数的形式返回。date可以是一个DATE字符串、DATETIME字符串、TIMESTAMP或一个当地时间的YYMMDD或YYYYMMDD格式的数字。
使用UNIX_TIMESTAMP函数返回UNIX格式的时间戳,输入语句如下:
select unix_timestamp(), unix_timestamp(now()), now();
+------------------+-----------------------+---------------------+
| unix_timestamp() | unix_timestamp(now()) | now() |
+------------------+-----------------------+---------------------+
| 1782216548 | 1782216548 | 2026-06-23 20:09:08 |
+------------------+-----------------------+---------------------+
FROM_UNIXTIME(date)函数把UNIX时间戳转换为普通格式的时间,与UNIX_TIMESTAMP (date)函数互为反函数。
使用FROM_UNIXTIME函数将UNIX时间戳转换为普通格式时间,输入语句如下:
select from_unixtime('154184424');
+----------------------------+
| from_unixtime('154184424') |
+----------------------------+
| 1974-11-20 21:00:24 |
+----------------------------+
可以看到,两个函数互为反函数。
4.4、返回UTC日期的函数和返回UTC时间的函数
UTC_DATE()函数返回当前UTC(世界标准时间)日期值,其格式为‘YYYY-MM-DD’或YYYYMMDD,具体格式取决于函数是否用在字符串或数字语境中。
使用UTC_DATE()函数返回当前UTC日期值,输入语句如下:
select utc_date(), utc_date() + 0;
+------------+----------------+
| utc_date() | utc_date() + 0 |
+------------+----------------+
| 2026-06-23 | 20260623 |
+------------+----------------+
UTC_DATE()函数返回值为当前时区的日期值。
UTC_TIME()返回当前UTC时间值,其格式为‘HH:MM:SS’或HHMMSS,具体格式取决于函数是否用在字符串或数字语境中。
使用UTC_TIME()函数返回当前UTC时间值,输入语句如下:
select utc_time(), utc_time() + 0;
+------------+----------------+
| utc_time() | utc_time() + 0 |
+------------+----------------+
| 12:21:07 | 122107 |
+------------+----------------+
UTC_TIME()返回当前时区的时间值。
4.5、获取月份的函数MONTH(date)和MONTHNAME(date)
MONTH(date)函数返回date对应的月份,范围值为1~12。
使用MONTH()函数返回指定日期中的月份,输入语句如下:
select month('2020-02-13');
+---------------------+
| month('2020-02-13') |
+---------------------+
| 2 |
+---------------------+
MONTHNAME(date)函数返回日期date对应月份的英文全名。
使用MONTHNAME()函数返回指定日期中月份的名称,输入语句如下:
select monthname('2018-02-13');
+-------------------------+
| monthname('2018-02-13') |
+-------------------------+
| February |
+-------------------------+
4.6、获取星期的函数DAYNAME(d)、DAYOFWEEK(d)和WEEKDAY(d)
DAYNAME(d)函数返回d对应的工作日的英文名称,例如Sunday、Monday等。
使用DAYNAME()函数返回指定日期的工作日名称,输入语句如下:
select dayname('2018-10-10');
+-----------------------+
| dayname('2018-10-10') |
+-----------------------+
| Wednesday |
+-----------------------+
可以看到,2018年10月10日是星期三,因此返回结果为Wednesday。
DAYOFWEEK(d)函数返回d对应的一周中的索引(位置,1表示周日,2表示周一,…,7表示周六)。
使用DAYOFWEEK()函数返回日期对应的周索引,输入语句如下:
select dayofweek('2018-10-10');
+-------------------------+
| dayofweek('2018-10-10') |
+-------------------------+
| 4 |
+-------------------------+
2018年10月10日为周三,因此返回其对应的索引值,结果为4。
WEEKDAY(d)返回d对应的工作日索引:0表示周一,1表示周二,…,6表示周日。
使用WEEKDAY()函数返回日期对应的工作日索引,输入语句如下:
select weekday('2018-10-10 22:23:00'), weekday('2018-11-11');
+--------------------------------+-----------------------+
| weekday('2018-10-10 22:23:00') | weekday('2018-11-11') |
+--------------------------------+-----------------------+
| 2 | 6 |
+--------------------------------+-----------------------+
可以看到,WEEKDAY()和DAYOFWEEK()函数都是返回指定日期在某一周内的位置,只是索引编号不同。
4.7、获取星期数的函数WEEK(d)和WEEKOFYEAR(d)
WEEK(d)计算日期d是一年中的第几周。WEEK()的双参数形式允许指定该星期是否起始于周日或周一,以及返回值的范围是否为053或153。若Mode参数被省略,则使用default_week_format系统自变量的值,可参考下表。

使用WEEK()函数查询指定日期是一年中的第几周,输入语句如下:
select week('2018-02-20'), week('2018-02-2-', 0), week('2018-02-20', 1);
+--------------------+-----------------------+-----------------------+
| week('2018-02-20') | week('2018-02-2-', 0) | week('2018-02-20', 1) |
+--------------------+-----------------------+-----------------------+
| 7 | 4 | 8 |
+--------------------+-----------------------+-----------------------+
可以看到,WEEK(‘2018-02-20’)使用一个参数,其第二个参数为default_week_format默认值,MySQL中该值默认为0,指定一周的第一天为周日,因此和WEEK(‘2018-02-20’,0)返回结果相同;WEEK(‘2018-02-20’,1)中第二个参数为1,指定一周的第一天为周一,返回值为8。可以看到,第二个参数不同,返回的结果也不同,使用不同的参数的原因是不同地区和国家的习惯不同,每周的第一天并不相同。
WEEKOFYEAR(d)计算某天位于一年中的第几周,范围是1~53,相当于WEEK(d,3)。
使用WEEKOFYEAR()查询指定日期是一年中的第几周,输入语句如下:
select week('2018-01-20', 3), weekofyear('2018-01-20');
+-----------------------+--------------------------+
| week('2018-01-20', 3) | weekofyear('2018-01-20') |
+-----------------------+--------------------------+
| 3 | 3 |
+-----------------------+--------------------------+
可以看到,两个函数返回结果相同。
4.8、获取天数的函数DAYOFYEAR(d)和DAYOFMONTH(d)
DAYOFYEAR(d)函数返回d是一年中的第几天,范围是1~366。
使用DAYOFYEAR()函数返回指定日期在一年中的位置,输入语句如下:
select dayofyear('2018-02-20');
+-------------------------+
| dayofyear('2018-02-20') |
+-------------------------+
| 51 |
+-------------------------+
DAYOFMONTH(d)函数返回d是一个月中的第几天,范围是1~31。
DAYOFMONTH(d)函数返回d是一个月中的第几天,范围是1~31。
select dayofmonth('2018-08-20');
+--------------------------+
| dayofmonth('2018-08-20') |
+--------------------------+
| 20 |
+--------------------------+
4.9、获取年份、季度、小时、分钟和秒钟的函数
YEAR(date)返回date对应的年份,范围是1970~2069。
使用YEAR()函数返回指定日期对应的年份,输入语句如下:
select year('18-02-03'), year('96-02-03');
+------------------+------------------+
| year('18-02-03') | year('96-02-03') |
+------------------+------------------+
| 2018 | 1996 |
+------------------+------------------+
QUARTER(date)返回date对应的一年中的季度值,范围是1~4。
使用QUARTER()函数返回指定日期对应的季度,输入语句如下:
select quarter('18-04-01');
+---------------------+
| quarter('18-04-01') |
+---------------------+
| 2 |
+---------------------+
MINUTE(time)返回time对应的分钟数,范围是0~59。
使用MINUTE()函数返回指定时间的分钟值,输入语句如下:
select minute('18-02-03 10:10:03');
+-----------------------------+
| minute('18-02-03 10:10:03') |
+-----------------------------+
| 10 |
+-----------------------------+
4.10、获取日期的指定值的函数EXTRACT(type FROM date)EXTRACT(type FROM date)
函数所使用的时间间隔类型说明符与DATE_ADD()或DATE_SUB()的相同,但它从日期中提取一部分,而不是执行日期运算。
使用EXTRACT函数提取日期或者时间值,输入语句如下:
select
extract(year from '2018-07-02') as col1,
extract(year_month from '2018-07-12 01:02:03') as col2,
extract(day_minute from '2018-07-12 01:02:03') as col3;
+------+--------+--------+
| col1 | col2 | col3 |
+------+--------+--------+
| 2018 | 201807 | 120102 |
+------+--------+--------+
type值为YEAR时,只返回年值,结果为2018;type值为YEAR_MONTH时返回年与月份,结果为201807;type值为DAY_MINUTE时,返回日、小时和分钟值,结果为120102。
4.11、时间和秒钟转换的函数
TIME_TO_SEC(time)返回已转化为秒的time参数。转换公式为:小时3600+分钟60+秒。
使用TIME_TO_SEC函数将时间值转换为秒值,输入语句如下:
select time_to_sec('23:23:00');
+-------------------------+
| time_to_sec('23:23:00') |
+-------------------------+
| 84180 |
+-------------------------+
SEC_TO_TIME(seconds)返回被转化为小时、分钟和秒数的seconds参数值,其格式为‘HH:MM:SS’或HHMMSS,具体格式根据该函数是否用在字符串或数字语境中而定。
使用SEC_TO_TIME()函数将秒值转换为时间格式,输入语句如下:
select
sec_to_time(2345),
sec_to_time(2345) + 0,
time_to_sec('23:23:00'),
sec_to_time(84180);
+-------------------+-----------------------+-------------------------+--------------------+
| sec_to_time(2345) | sec_to_time(2345) + 0 | time_to_sec('23:23:00') | sec_to_time(84180) |
+-------------------+-----------------------+-------------------------+--------------------+
| 00:39:05 | 3905 | 84180 | 23:23:00 |
+-------------------+-----------------------+-------------------------+--------------------+
可以看到,SEC_TO_TIME函数返回值加上0值之后变成了小数值;TIME_TO_SEC正好和SEC_TO_TIME互为反函数。
4.12、计算日期和时间的函数
计算日期和时间的函数有DATE_ADD()、ADDDATE()、DATE_SUB()、SUBDATE()、ADDTIME()、SUBTIME()和DATE_DIFF()。
在DATE_ADD(date,INTERVAL expr type)和DATE_SUB(date,INTERVAL expr type)中,date是一个DATETIME或DATE值,用来指定起始时间。expr是一个表达式,用来指定从起始日期添加或减去的时间间隔值。对于负值的时间间隔,expr可以以一个负号‘-’开头。type为关键词,指示了表达式被解释的方式。
下表显示了type和expr参数的关系。

若date参数是一个DATE值,计算只会包括YEAR、MONTH和DAY部分(没有时间部分),其结果是一个DATE值;否则,结果将是一个DATETIME值。
DATE_ADD(date,INTERVAL expr type)和ADDDATE(date,INTERVAL expr type)两个函数的作用相同,执行日期的加运算。
使用DATE_ADD()和ADDDATE()函数执行日期加操作,输入语句如下:
select
date_add('2010-12-31 23:59:59', interval 1 second) as col1,
adddate('2010-12-31 23:59:59', interval 1 second) as col2,
date_add('2010-12-31 23:59:59', interval '1:1' minute_second) as col3;
+---------------------+---------------------+---------------------+
| col1 | col2 | col3 |
+---------------------+---------------------+---------------------+
| 2011-01-01 00:00:00 | 2011-01-01 00:00:00 | 2011-01-01 00:01:00 |
+---------------------+---------------------+---------------------+
由结果可以看到,DATE_ADD(‘2010-12-3123:59:59’, INTERVAL 1 SECOND)和ADDDATE(‘2010-12-31 23:59:59’,INTERVAL 1 SECOND)两个函数执行的结果是相同的,将时间增加1秒后返回,结果都为‘2011-01-01 00:00:00’;DATE_ADD(‘2010-12-31 23:59:59’,INTERVAL ‘1:1’ MINUTE_SECOND)日期运算类型是MINUTE_SECOND,将指定时间增加1分1秒后返回,结果为‘2011-01-0100:01:00’。
DATE_SUB(date,INTERVAL expr type)或者SUBDATE(date,INTERVAL expr type)两个函数的作用相同,执行日期的减运算。
使用DATE_SUB和SUBDATE函数执行日期减操作,输入语句如下:
select
date_sub('2011-01-02', interval 31 day) as col1,
subdate('2011-01-02', interval 31 day) as col2,
date_sub('2011-01-01 00:01:00', interval '0 0:1:1' day_second) as col3;
+------------+------------+---------------------+
| col1 | col2 | col3 |
+------------+------------+---------------------+
| 2010-12-02 | 2010-12-02 | 2010-12-31 23:59:59 |
+------------+------------+---------------------+
由结果可以看到,DATE_SUB(‘2011-01-02’,INTERVAL 31 DAY)和SUBDATE(‘2011-01-02’, INTERVAL 31 DAY)两个函数执行的结果是相同的,将日期值减少31天后返回,结果都为“2010-12-02”;DATE_SUB(‘2011-01-01 00:01:00’,INTERVAL '0 0:1:1’DAY_SECOND)函数将指定日期减少1天,时间减少1分1秒后返回,结果为“2010-12-3123:59:59”。
DATE_ADD和DATE_SUB在指定修改的时间段时,也可以指定负值,负值代表相减,即返回以前的日期和时间。
ADDTIME(date,expr)函数将expr值添加到date,并返回修改后的值,date是一个日期或者日期时间表达式,而expr是一个时间表达式。
使用ADDTIME进行时间加操作,输入语句如下:
select
addtime('2000-12-31 23:59:59', '1:1:1'),
addtime('02:02:02','02:00:00');
+-----------------------------------------+--------------------------------+
| addtime('2000-12-31 23:59:59', '1:1:1') | addtime('02:02:02','02:00:00') |
+-----------------------------------------+--------------------------------+
| 2001-01-01 01:01:00 | 04:02:02 |
+-----------------------------------------+--------------------------------+
可以看到,将“2000-12-31 23:59:59”的时间部分值增加1小时1分钟1秒后的日期变为“2001-01-01 01:01:00”;“02:02:02”增加两小时后的时间为“04:02:02”。
SUBTIME(date,expr)函数将date减去expr值,并返回修改后的值。其中,date是一个日期或者日期时间表达式,而expr是一个时间表达式。
使用SUBTIME()函数执行时间减操作,输入语句如下:
select subtime('2000-12-31 23:59:59', '1:1:1'), subtime('02:02:02', '02:00:00');
+-----------------------------------------+---------------------------------+
| subtime('2000-12-31 23:59:59', '1:1:1') | subtime('02:02:02', '02:00:00') |
+-----------------------------------------+---------------------------------+
| 2000-12-31 22:58:58 | 00:02:02 |
+-----------------------------------------+---------------------------------+
可以看到,将“2000-12-31 23:59:59”的时间部分值减少1小时1分钟1秒后的日期变为“2000-12-31 22:58:58”; “02:02:02”减少两小时的时间为“00:02:02”。
DATEDIFF(date1,date2)返回起始时间date1和结束时间date2之间的天数。date1和date2为日期或日期时间表达式。计算中只用到这些值的日期部分。
使用DATEDIFF()函数计算两个日期之间的间隔天数,输入语句如下:
select
datediff('2010-12-31 23:59:59', '2010-12-30') as col1,
datediff('2010-11-3- 23:59:59', '2010-12-31') as col2;
+------+------+
| col1 | col2 |
+------+------+
| 1 | -58 |
+------+------+
DATEDIFF()函数返回date1-date2后的值,因此DATEDIFF(‘2010-12-3123:59:59’,‘2010-12-30’)返回值为1;DATEDIFF(‘2010-11-30 23:59:59’,‘2010-12-31’)返回值为-31。
4.13、将日期和时间格式化的函数
DATE_FORMAT(date,format)根据format指定的格式显示date值。主要format格式如表所示。

使用DATE_FORMAT()函数格式化输出日期和时间值,输入语句如下:
select
date_format('1997-10-04 22:23:00', '%W %M %Y') as col1,
date_format('1997-10-04 22:23:00', '%D %y %a %d %m %b %j') as col2;
+-----------------------+--------------------------+
| col1 | col2 |
+-----------------------+--------------------------+
| Saturday October 1997 | 4th 97 Sat 04 10 Oct 277 |
+-----------------------+--------------------------+
可以看到“1997-10-04 22:23:00”分别按照不同参数转换成了不同格式的日期值和时间值。
TIME_FORMAT(time,format)根据表达式format的要求显示时间time。表达式format指定了显示的格式。因为TIME_FORMAT(time,format)只处理时间,所以format只使用时间格式。
使用TIME_FORMAT()函数格式化输入时间值,输入语句如下:
select time_format('16:00:00', '%H %k %h %I %l');
+-------------------------------------------+
| time_format('16:00:00', '%H %k %h %I %l') |
+-------------------------------------------+
| 16 16 04 04 4 |
+-------------------------------------------+
TIME_FORMAT只处理时间值,可以看到,“16:00:00”按照不同的参数转换为不同格式的时间值。
GET_FORMAT(val_type, format_type)返回日期时间字符串的显示格式,val_type表示日期数据类型,包括DATE、DATETIME和TIME;format_type表示格式化显示类型,包括EUR、INTERVAL、ISO、JIS、USA。GET_FORMAT根据两个值类型组合返回的字符串显示格式如表所示。

使用GET_FORMAT()函数显示不同格式化类型下的格式字符串,输入语句如下:
select get_format(date, 'EUR'), get_format(date, 'USA');
+-------------------------+-------------------------+
| get_format(date, 'EUR') | get_format(date, 'USA') |
+-------------------------+-------------------------+
| %d.%m.%Y | %m.%d.%Y |
+-------------------------+-------------------------+
5、条件判断函数
条件判断函数也称为控制流程函数,根据满足的不同条件,执行相应的流程。MySQL中进行条件判断的函数有IF、IFNULL和CASE。
5.1、IF(expr,v1,v2)函数
IF(expr, v1, v2):如果表达式expr是TRUE(expr <> 0 and expr <> NULL),则返回值为v1;否则返回值为v2。IF()的返回值为数字值或字符串值,具体情况视其所在语境而定。
使用IF()函数进行条件判断,输入语句如下:
select
if(1>2, 2, 3),
if(1<2, 'yes ', 'no '),
if(strcmp('test', 'test1'), 'no', 'yes');
+---------------+------------------------+------------------------------------------+
| if(1>2, 2, 3) | if(1<2, 'yes ', 'no ') | if(strcmp('test', 'test1'), 'no', 'yes') |
+---------------+------------------------+------------------------------------------+
| 3 | yes | no |
+---------------+------------------------+------------------------------------------+
1>2的结果为FALSE,IF(1>2,2,3)返回第2个表达式的值;1<2的结果为TRUE,IF(1<2,'yes ', ‘no’)返回第一个表达式的值;“test”小于“test1”,结果为true,IF(STRCMP(‘test’,‘test1’),‘no’,‘yes’)返回第一个表达式的值。
如果v1或v2中只有一个明确是NULL,则IF()函数的结果类型为非NULL表达式的结果类型。
5.2、IFNULL(v1,v2)函数
IFNULL(v1,v2):假如v1不为NULL,则IFNULL()的返回值为v1;否则其返回值为v2。IFNULL()的返回值是数字或者字符串,具体情况取决于其所在的语境。
使用IFNULL()函数进行条件判断,输入语句如下:
select ifnull(1, 2), ifnull(null, 10), ifnull(1/0, 'wrong');
+--------------+------------------+----------------------+
| ifnull(1, 2) | ifnull(null, 10) | ifnull(1/0, 'wrong') |
+--------------+------------------+----------------------+
| 1 | 10 | wrong |
+--------------+------------------+----------------------+
IFNULL(1,2)虽然第二个值也不为空,但返回结果依然是第一个值;IFNULL(NULL,10)第一个值为空,因此返回10;“1/0”的结果为空,因此IFNULL(1/0, ‘wrong’)返回字符串“wrong”。
5.3、CASE函数
CASE expr WHEN v1 THEN r1 [WHEN v2THEN r2]…[ELSE rn+1] END:如果expr值等于某个vn,则返回对应位置THEN后面的结果;如果与所有值都不相等,则返回ELSE后面的rn+1。
使用CASE value WHEN语句执行分支操作,输入语句如下:
select case 2
when 1 then 'one'
when 2 then 'two'
else 'more' end;
+---------+
| case 2 |
| when 1 then 'one' |
| when 2 then 'two' |
| else 'more' end |
+---------+
| two |
+---------+
CASE后面的值为2,与第二条分支语句WHEN后面的值相等,因此返回结果为“two”。
CASE WHEN v1 THEN r1 [WHEN v2THEN r2]… ELSE rn+1] END:某个vn值为TRUE时,返回对应位置THEN后面的结果;如果所有值都不为TRUE,则返回ELSE后的rn+1。
使用CASE WHEN语句执行分支操作,输入语句如下:
select case
when 1<0 then 'true'
else 'false' end;
+-------+
| case |
| when 1<0 then 'true' |
| else 'false' end |
+-------+
| false |
+-------+
1<0的结果为FALSE,因此函数返回值为ELSE后面的“false”。
6、系统信息函数
MySQL中的系统信息有数据库的版本号、当前用户名和连接数、系统字符集、最后一个自动生成的ID值等。
6.1、获取MySQL版本号、连接数和数据库名的函数
VERSION()返回指示MySQL服务器版本的字符串。这个字符串使用utf8字符集。
查看当前MySQL版本号,输入语句如下:
select version();
+-------------------------+
| version() |
+-------------------------+
| 8.0.30-cynos-3.1.16.006 |
+-------------------------+
CONNECTION_ID()返回MySQL服务器当前连接的次数,每个连接都有各自唯一的ID。
查看当前用户的连接数,输入语句如下:
select connection_id();
+-----------------+
| connection_id() |
+-----------------+
| 199807 |
+-----------------+
SHOW PROCESSLIST;
SHOW FULL PROCESSLIST;
processlist命令的输出结果显示了有哪些线程在运行,不仅可以查看当前所有的连接数,还可以查看当前的连接状态、帮助识别出有问题的查询语句等。
如果是root账号,能看到所有用户的当前连接。如果是其他普通账号,则只能看到自己占用的连接。show processlist只列出前100条,如果想全部列出可使用show fullprocesslist命令。
使用SHOW PROCESSLIST命令输出当前用户的连接信息,输入语句如下:
show processlist;
+--------+------+----------------------+---------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+--------+------+----------------------+---------+---------+------+-------+------------------+
| 199807 | root | 175.31.236.166:24460 | test_db | Query | 0 | init | show processlist |
+--------+------+----------------------+---------+---------+------+-------+------------------+
各个列的含义和用途:
- Id列,用户登录MySQL时,系统分配的是“connection id”。
- User列,显示当前用户。如果不是root,这个命令就只显示用户权限范围内的SQL语句。
- Host列,显示这个语句是从哪个IP的哪个端口上发出的,可以用来追踪出现问题语句的用户。
- db列,显示这个进程目前连接的是哪个数据库。
- Command列,显示当前连接执行的命令,一般取值为休眠(Sleep)、查询(Query)、连接(Connect)。
- Time列,显示这个状态持续的时间,单位是秒。
- State列,显示使用当前连接的SQL语句的状态,很重要的列。后续会有所有状态的描述,State只是语句执行中的某一个状态。一个SQL语句,以查询为例,可能需要经过Copying to tmp table、Sortingresult、Sending data等状态才可以完成。
- Info列,显示这个SQL语句,是判断问题语句的一个重要依据。
DATABASE()和SCHEMA()函数返回使用utf8字符集的默认(当前)数据库名。
查看当前使用的数据库,输入语句如下:
select database(), schema();
+------------+----------+
| database() | schema() |
+------------+----------+
| test_db | test_db |
+------------+----------+
可以看到,两个函数的作用相同。
6.2、获取用户名的函数
USER()、CURRENT_USER、CURRENT_USER()、SYSTEM_USER()和SESSION_USER()这几个函数返回当前被MySQL服务器验证的用户名和主机名组合。这个值符合确定当前登录用户存取权限的MySQL账户。一般情况下,这几个函数的返回值是相同的。
获取当前登录用户名称,输入语句如下:
select user(), current_user(), system_user();
+---------------------+----------------+---------------------+
| user() | current_user() | system_user() |
+---------------------+----------------+---------------------+
| root@175.31.236.166 | root@% | root@175.31.236.166 |
+---------------------+----------------+---------------------+
返回结果值指示了当前账户连接服务器时的用户名及所连接的客户主机,root为当前登录的用户名,localhost为登录的主机名。
6.3、获取字符串的字符集和排序方式的函数
CHARSET(str)返回字符串str自变量的字符集。
使用CHARSET()函数返回字符串使用的字符集,输入语句如下:
select
charset('abc'),
charset(convert('abc' using latin1)),
charset(version());
+----------------+--------------------------------------+--------------------+
| charset('abc') | charset(convert('abc' using latin1)) | charset(version()) |
+----------------+--------------------------------------+--------------------+
| utf8mb4 | latin1 | utf8mb3 |
+----------------+--------------------------------------+--------------------+
CHARSET(‘abc’)返回系统默认的字符集utf8;CHARSET(CONVERT(‘abc’ USINGlatin1))返回的字符集为latin1;前面介绍过,VERSION()返回的字符串使用utf8字符集,因此CHARSET返回结果为utf8。
COLLATION(str)返回字符串str的字符排列方式。
使用COLLATION()函数返回字符串排列方式,输入语句如下:
select
collation('abc'),
collation(convert('abc' using utf8));
+--------------------+--------------------------------------+
| collation('abc') | collation(convert('abc' using utf8)) |
+--------------------+--------------------------------------+
| utf8mb4_0900_ai_ci | utf8mb3_general_ci |
+--------------------+--------------------------------------+
可以看到,使用不同字符集时字符串的排列方式不同。
6.4、获取最后一个自动生成的ID值的函数
LAST_INSERT_ID()函数返回最后生成的AUTO_INCREMENT值。
使用SELECT LAST_INSERT_ID查看最后一个自动生成的列值。
1.一次插入一条记录
首先创建表worker,其Id字段带有AUTO_INCREMENT约束,输入语句如下:
create table worker
(
id int auto_increment primary key,
name varchar(30)
);
分别单独向表worker中插入两条记录:
insert into worker values(null, 'jimy');
insert into worker values(null, 'Tom');
select * from worker;
+----+------+
| id | name |
+----+------+
| 1 | jimy |
| 2 | Tom |
+----+------+
查看已经插入的数据可以发现,最后一条插入的记录的Id字段值为2,使用LAST_INSERT_ID()查看最后自动生成的Id值:
select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 2 |
+------------------+
可以看到,一次插入一条记录时,返回值为最后一条插入记录的Id值。
2.一次同时插入多条记录
接下来,向表中插入多条记录,输入语句如下:
insert into worker values
(null, 'Kevin'),
(null, 'Michal'),
(null, 'Nick');
查询已经插入的记录:
select * from worker;
+----+--------+
| id | name |
+----+--------+
| 1 | jimy |
| 2 | Tom |
| 3 | Kevin |
| 4 | Michal |
| 5 | Nick |
+----+--------+
可以看到最后一条记录的Id字段值为5,使用LAST_INSERT_ID()查看最后自动生成的Id值:
select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 3 |
+------------------+
结果显示,LAST_INSERT_ID值不是5而是3,这是为什么呢?在向数据表中插入一条新记录时,LAST_INSERT_ID()返回带有AUTO_INCREMENT约束的字段最新生成的值2;继续向表中同时添加3条记录,读者可能以为这时LAST_INSERT_ID值为5,可显示结果却为3,这是因为当使用一条INSERT语句插入多行时,LAST_INSERT_ID()只返回插入的第一行数据时产生的值,在这里为第3条记录。之所以这样,是因为这使依靠其他服务器复制同样的INSERT语句变得简单。
LAST_INSERT_ID是与数据表无关的,如果向表a插入数据后再向表b插入数据,那么LAST_INSERT_ID返回表b中的Id值。
7、其它函数
7.1、格式化函数FORMAT(x,n)
FORMAT(x,n)将数字x格式化,并以四舍五入的方式保留小数点后n位,结果以字符串的形式返回。若n为0,则返回结果函数不含小数部分。
使用FORMAT函数格式化数字,保留小数点位数为指定值,输入语句如下:
select
format(12332.123456, 4),
format(12332.1, 4),
format(12332.2, 0);
+-------------------------+--------------------+--------------------+
| format(12332.123456, 4) | format(12332.1, 4) | format(12332.2, 0) |
+-------------------------+--------------------+--------------------+
| 12,332.1235 | 12,332.1000 | 12,332 |
+-------------------------+--------------------+--------------------+
由结果可以看到,FORMAT(12332.123456,4)保留4位小数点值,并进行四舍五入,结果为12332.1235;FORMAT(12332.1,4)保留4位小数值,位数不够的用0补齐;FORMAT(12332.2,0)不保留小数位值,返回结果为整数12332。
7.2、不同进制的数字进行转换的函数
CONV(N, from_base, to_base)函数进行不同进制数间的转换。返回值为数值N的字符串表示,由from_base进制转化为to_base进制。如有任意一个参数为NULL,则返回值为NULL。自变量N被理解为一个整数,但是可以被指定为一个整数或字符串。最小基数为2,最大基数为36。
使用CONV函数在不同进制数值之间转换,输入语句如下:
select
conv('a', 16, 2),
conv(15, 10, 2),
conv(15, 10, 8),
conv(15, 10, 16);
+------------------+-----------------+-----------------+------------------+
| conv('a', 16, 2) | conv(15, 10, 2) | conv(15, 10, 8) | conv(15, 10, 16) |
+------------------+-----------------+-----------------+------------------+
| 1010 | 1111 | 17 | F |
+------------------+-----------------+-----------------+------------------+
CONV(‘a’,16,2)将十六进制的a转换为二进制表示的数值,十六进制的a表示十进制的数值10,二进制的数值1010正好等于十进制的数值10;CONV(15,10,2)将十进制的数值15转换为二进制值,结果为1111;CONV(15,10,8)将十进制的数值15转换为八进制值,结果为17;CONV(15,10,16)将十进制的数值15转换为十六进制值,结果为F。
7.3、IP地址与数字相互转换的函数
INET_ATON(expr)给出一个作为字符串的网络地址的点地址表示,返回一个代表该地址数值的整数。地址可以是4或8bit地址。
使用INET_ATON函数将字符串网络点地址转换为数值网络地址,输入语句如下:
select inet_aton('209.207.224.40');
+-----------------------------+
| inet_aton('209.207.224.40') |
+-----------------------------+
| 3520061480 |
+-----------------------------+
INET_NTOA(expr)给定一个数字网络地址(4或8bit),返回作为字符串的该地址的点地址表示。
使用INET_NTOA函数将数值网络地址转换为字符串网络点地址,输入语句如下:
select inet_ntoa(3520061480);
+-----------------------+
| inet_ntoa(3520061480) |
+-----------------------+
| 209.207.224.40 |
+-----------------------+
可以看到,INET_NTOA和INET_ATON互为反函数。
7.4、加锁函数和解锁函数
-
GET_LOCK(str,timeout)设法使用字符串str给定的名字得到一个锁,超时为timeout秒。若成功得到锁,则返回1;若操作超时,则返回0;若发生错误,则返回NULL。假如有一个用GET_LOCK()得到的锁,当执行RELEASE_LOCK()或连接断开(正常或非正常)时,这个锁就会解除。 -
RELEASE_LOCK(str)解开被GET_LOCK()获取的、用字符串str所命名的锁。若锁被解开,则返回1;若该线程尚未创建锁,则返回0(此时锁没有被解开);若命名的锁不存在,则返回NULL。若该锁从未被GET_LOCK()的调用获取,或锁已经被提前解开,则该锁不存在。 -
IS_FREE_LOCK(str)检查名为str的锁是否可以使用(换言之,没有被封锁)。若锁可以使用,则返回1(没有人在用这个锁);若这个锁正在被使用,则返回0;出现错误,则返回NULL(诸如不正确的参数)。 -
IS_USED_LOCK(str)检查名为str的锁是否正在被使用(换言之,被封锁)。若被封锁,则返回使用该锁的客户端的连接标识符(connection ID);否则,返回NULL。
使用加锁、解锁函数,输入语句如下:
select
get_lock('lock1', 10) as GetLock,
is_used_lock('lock1') as ISUsedLock,
is_free_lock('lock1') as ISFreeLock,
release_lock('lock1') as ReleaseLock;
+---------+------------+------------+-------------+
| GetLock | ISUsedLock | ISFreeLock | ReleaseLock |
+---------+------------+------------+-------------+
| 1 | 199807 | 0 | 1 |
+---------+------------+------------+-------------+
GET_LOCK(‘lock1’,10)返回结果为1,说明成功得到了一个名称为‘lock1’的锁,持续时间为10秒。
IS_USED_LOCK(‘lock1’)返回结果为当前连接ID,表示名称为‘lock1’的锁正在被使用。
IS_FREE_LOCK(‘lock1’)返回结果为0,说明名称为‘lock1’的锁正在被使用。
RELEASE_LOCK(‘lock1’)返回值为1,说明解锁成功。
7.5、重复执行指定操作的函数
BENCHMARK(count,expr)函数重复count次执行表达式expr。它可以用于计算MySQL处理表达式的速度。结果值通常为0(0只是表示处理过程很快,并不是没有花费时间)。另一个作用是它可以在MySQL客户端内部报告语句执行的时间。
使用BENCHMARK重复执行指定函数。
首先,使用PASSWORD函数加密密码,输入语句如下:
select sha('newpwd');
+------------------------------------------+
| sha('newpwd') |
+------------------------------------------+
| c7f005b657906521157aa3fc261afe886d51f792 |
+------------------------------------------+
1 row in set
Time: 0.065s
可以看到,PASSWORD执行花费时间为0.065sec。下面使用BENCHMARK函数重复执行PASSWORD操作500000次:
select benchmark(500000, sha('newpwd'));
+----------------------------------+
| benchmark(500000, sha('newpwd')) |
+----------------------------------+
| 0 |
+----------------------------------+
1 row in set
Time: 0.201s
由此可以看出,使用BENCHMARK执行500000次的时间为0.201 sec,明显比执行一次的时间延长了。
7.6、改变字符集的函数
CONVERT(… USING …):带有USING的CONVERT()函数被用来在不同的字符集之间转化数据。
使用CONVERT()函数改变字符串的默认字符集,输入语句如下:
select
charset('string'),
charset(convert('string' using latin1));
+-------------------+-----------------------------------------+
| charset('string') | charset(convert('string' using latin1)) |
+-------------------+-----------------------------------------+
| utf8mb4 | latin1 |
+-------------------+-----------------------------------------+
默认为gbk字符集,通过CONVERT将字符串“string”的默认字符集改为latin1。
7.7、改变数据类型的函数
CAST(x, AS type)和CONVERT(x, type)函数将一个类型的值转换为另一个类型的值,可转换的type有BINARY、CHAR(n)、DATE、TIME、DATETIME、DECIMAL、SIGNED、UNSIGNED。
使用CAST和CONVERT函数进行数据类型的转换,SQL语句如下:
select
cast(100 as char(2)),
convert('2018-10-01 12:12:12', time);
+----------------------+--------------------------------------+
| cast(100 as char(2)) | convert('2018-10-01 12:12:12', time) |
+----------------------+--------------------------------------+
| 10 | 12:12:12 |
+----------------------+--------------------------------------+
可以看到,CAST(100 AS CHAR(2))将整数数据100转换为带有两个显示宽度的字符串类型,结果为‘10’;CONVERT(‘2018-10-0112:12:12’,TIME)将DATETIME类型的值转换为TIME类型值,结果为‘12:12:12’。
8、MySQL8.0新特性——加密函数
8.1、加密函数MD5(str)
MD5(str)为字符串算出一个MD5 128比特校验和。该值以32位十六进制数字的二进制字符串形式返回,若参数为NULL,则会返回NULL。
使用MD5函数加密字符串,输入语句如下:
select md5('mypwd');
+----------------------------------+
| md5('mypwd') |
+----------------------------------+
| 318bcb4be908d0da6448a0db76908d78 |
+----------------------------------+
8.2、加密函数SHA(str)
SHA(str)从原明文密码str计算并返回加密后的密码字符串,当参数为NULL时,返回NULL。SHA加密算法比MD5更加安全。
使用SHA函数加密密码,输入语句如下:
select sha('tom123456');
+------------------------------------------+
| sha('tom123456') |
+------------------------------------------+
| 8218b487f490cb484f45c31403eb1f597a2b531a |
+------------------------------------------+
8.3、加密函数SHA2(str, hash_length)
SHA2(str, hash_length)使用hash_length作为长度,加密str。hash_length支持的值为224、256、384、512和0。其中,0等同于256。
使用SHA2加密字符串,输入语句如下:
select sha2('tom123456', 0) A, sha2('tom123456', 256) B\G;
***************************[ 1. row ]***************************
A | 9242a986a9edbd14a60450e9284a372efeff7e9f6209f675fdc4457f55de5e27
B | 9242a986a9edbd14a60450e9284a372efeff7e9f6209f675fdc4457f55de5e27
可以看到,hash_length的值为256和0时,结果都是一样的。
9、MySQL8.0新特性——窗口函数
在MySQL 8.0版本之前,没有排名函数,所以当需要在查询当中实现排名时,必须手写@变量,比较麻烦。
在MySQL 8.0版本中,新增了一个窗口函数,用它可以实现很多新的查询方式。窗口函数类似于SUM()、COUNT()那样的集合函数,但它并不会将多行查询结果合并为一行,而是将结果放回多行当中。也就是说,窗口函数是不需要GROUP BY的。
下面通过案例来讲述通过窗口函数实现排名效果的方法。
创建公司部门表branch,包含部门的名称和部门人数两个字段,创建语句如下:
create table branch
(
name char(255) not null,
brcount int(11) not null
);
insert into branch(name, brcount) values
('branch1', 5),
('branch2', 10),
('branch3', 8),
('branch4', 20),
('branch5', 9);
对公司部门人数按从小到大进行排名,可以利用窗口函数来实现:
select *,
rank() over w1 as `rank `
from branch
window w1 as (order by brcount);
+---------+---------+-------+
| name | brcount | rank |
+---------+---------+-------+
| branch1 | 5 | 1 |
| branch3 | 8 | 2 |
| branch5 | 9 | 3 |
| branch2 | 10 | 4 |
| branch4 | 20 | 5 |
+---------+---------+-------+
这里创建了名称为w1的窗口函数,规定对brcount字段进行排序,然后在SELECT子句中对窗口函数w1执行rank()方法,将结果输出为rank字段。
需要注意,这里的window w1是可选的。例如,在每一行中加入员工的总数,可以这样操作:
select *,
sum(brcount) over() as total_count
from branch;
+---------+---------+-------------+
| name | brcount | total_count |
+---------+---------+-------------+
| branch1 | 5 | 52 |
| branch2 | 10 | 52 |
| branch3 | 8 | 52 |
| branch4 | 20 | 52 |
| branch5 | 9 | 52 |
+---------+---------+-------------+
可以一次性查询出每个部门的员工人数占总人数的百分比,查询结果如下:
select *,
(brcount) / (sum(brcount) over()) as rate
from branch;
+---------+---------+--------+
| name | brcount | rate |
+---------+---------+--------+
| branch1 | 5 | 0.0962 |
| branch2 | 10 | 0.1923 |
| branch3 | 8 | 0.1538 |
| branch4 | 20 | 0.3846 |
| branch5 | 9 | 0.1731 |
+---------+---------+--------+
2040

被折叠的 条评论
为什么被折叠?



