SQL函数(复盘)

发布于 2022-05-14  3.53k 次阅读


一,函数的分类

函数的概念:函数在学习编程种非常常见,它要对代码逻辑进行封装,需要时直接调用即可,这样能提升效率,也能提高维护性。在SQL中也可以使用函数对检索出来的数据进行函数操作,使得这些函数,可以极大地提高用户对数据库的管理效率

从函数定义角度进行分类:

  •  内置函数:系统内置的通用函数
  • 自定义函数:根据要求自己编写

在SQL语言中,同样也包括内置函数和自定义函数

 1,不同DBMS函数的差异

使用SQL语言的时候,直接作用于数据库软件,即DBMS(Oracle,Mysql,SqlServer……),它们之间的内置函数的差异是比较大的。实际上只有很少一部分函数被共同支持的。比如:大多数DBMS使用(||)或者(+)来做拼接符,而在Mysql中字符串的拼接需要使用函数concat()
大多数DBMS都有自己特定的函数,这就意味着采用SQL函数的代码可移植性是很差的

2,MySQL的内置函数分类

Mysql提供了丰富的内置函数,这些函数使得数据的维护与管理更加方便,能够更好的提供数据分析与统计功能,在一定程度上提高了开发人员进行数据分析与统计的效率

MySQL函数从功能上分类:

  1. 数值函数
  2. 字符串函数
  3. 日期和时间函数
  4. 流程控制函数
  5. 加密和解密函数
  6. 获取Mysql信息函数
  7. 聚合函数

主要分为两类:

  • 单行函数
  • 聚合函数(或:分组函数)

单行函数的定义:单行函数作用于一组数据(列),对单行的数据进行操作变换,最终得出单行结果

聚合函数的定义:聚合函数作用于一组数据(列),并对该组数据进行汇总,最后返回一个值

二,数值函数

一,基本数值函数

函数
用法
ABS(x)
返回x的绝对值
SIGN(x)
返回x的符号,正数返回1,负数返回-1,0返回0
PI()
返回圆周率的值
CEIL(x),CEILING(x)
返回大于或等于某个值的最小整数
FLOOR(x)
返回小于或等于某个值的最大整数
LEAST(e1,e2,e3……)
返回列表中的最小值
GREATEST
返回列表中的最大值
MOD(x,y)
返回x除以y后的余数
RAND()
返回0-1的随机数
RAND(x)
返回0-1的随机数,x作为种子值,相同的x值会产生相同的随机数
ROUND(x)
返回一个对x的值进行四舍五入,最接近x的值
ROUND(x,y)
返回一个对x的值进行四舍五入最接近x的值,并保留到小数点后y位
TRUNCATE(x,y)
返回数字x截断为y位小数的结果
SQRT(x)
返回x的平方根,当x的值为负数时,返回NULL

例1:

SELECT ABS(10),ABS(-2),SIGN(-12),SIGN(10),CEIL(32.123),FLOOR(-21.21),LEAST(11,123,21,212),GREATEST(12,123,122),MOD(10,3);

例2:随机数(同样的种子生成的随机数相同)

SELECT RAND(),RAND()*1000000,RAND(2),RAND(2),RAND(10);

例3:取整,保留小数,截断

SELECT ROUND(10.42),ROUND(10.52),ROUND(10.81,1),ROUND(10.73,2),TRUNCATE(23.12,-1),TRUNCATE(23.12,-2),TRUNCATE(23.12,2);

例4:函数嵌套 --> 生成一个7位数的验证码

SELECT TRUNCATE(RAND()*10000000,0);


二,进制转化函数

函数
用法
BIN(x)
返回x的二进制编码
OCT(x)
返回x的八进制编码
HEX(x)
返回x的十六进制编码
CONV(x,y,z)
返回y进制数变成z进制数
例:
SELECT BIN(4),OCT(4),HEX(15),CONV(4,10,2);

三,指数与对数函数

函数
用法
POW(x,y) 或 POWER(x,y)
返回x的y次方
EXP(x)
返回e的x次方,其中e是一个常数,2.7182818……
LN(x) 或 LOG(x)
返回以e为底的x的对数,当x<=0时,返回的结果为NULL
LOG10(x)
返回以10为底的x的对数,当x<=0时,返回结果为NULL
LOG2(x)
返回2为底x的对数,当x<=0时,返回NULL
例:
SELECT POW(2,5),EXP(4),LN(17),LOG10(42),LOG2(5);

三,字符串函数

函数 用法
ASCII(s) 返回字符串s中的第一个字符的ASCII码值
CHAR_LENGTH(s) 返回字符串s的字符数
LENGTH(s) 返回字符串s的字节数,和字符集有关
CONCAT(s1,s2,…sn) 连接s1,s2…sn为一个字符串
CONCAT_WS(x,s1,s2…sn) 和CONCAT是一样,但在每一个字符串之间要加上x
INSERT(str,idx,len,replacestr) 将字符串str从第idx的位置,len个字符长的子串替换为字符串replacestr
REPLACE(str,a,b) 有字符串b替换字符串str中所出现的字符串a
UPPER(s) 或 UCASE(s) 将字符串s的所有字母转换成大写字母
LOWER(s) 或 LCASE(s) 将字符串s的所有字母转换成小写字母
LEFT(str,n) 返回字符串str最左边的n个字符
RIGNT(str,n) 返回字符串str最右边的n个字符
LPAD(str,len,pad) 用字符串pad对str最左边进行填充。直到str的长度为len个字符
RPAD(str,len,pad) 用字符串pad对str最右边进行填充。直到str的长度为len个字符
LTRIM(s) 去掉字符串s左侧的空格
RTRIM(s) 去掉字符串s右侧的空格
TRIM(s) 去掉字符串s左右侧的空格
TRIM(s1 FROM s) 去掉字符串s开始和结尾处的s1
TRIM(LEADING s1 FROM s) 去掉字符串s开始处的s1
TRIM(TRAILING s1 FROM s) 去掉字符串s结尾处的s1
REPEAT(str,n) 返回str重复n次的结果
SPACE(n) 返回n个空格
STRCMP(s1,s2) 比较字符串s1,s2的ASCII码值的大小
SUBSTR(s,index,len) 返回从字符串s的index位置其len个字符,作用与SUBSTRING(s,n,len)相同
LOCATE(substr,str)

ELT(m,s1,s2,…,sn)

返回字符串substr在字符串str中首次出现的位置,作用和POSITION(substr IN str),INSTR(str,substr)相同。未找到返回0

返回指定位置的字符串,如果m=1,则返回s1,如果m=2则返回s2以此类推

FIELD(s,s1,s2,…,sn) 返回字符串s在字符串列表中第一次出现的位置
FIND_IN_SET(s1,s2) 返回字符串s1在字符串s2中出现的位置,其中,字符串s2是一个以逗号分隔的字符串

例1:字符或字节长度的获取

  • 在UTF-8编码中一个中文字符占3个字节,英文字母占一个字节
  • 一个英文虽然只占一个字节,但在char_length它也是一个字符
  • CHAR_LENGTH(s)获取字符数,LENGTH(s)获取字节数
SELECT CHAR_LENGTH("风铃"),LENGTH("凌风"),CHAR_LENGTH("Hello"),LENGTH("Hello");

例2:字符串的拼接

  • CONCAT(s1,s2,…sn)
  • CONCAT_WS(x,s1,s2…sn)
SELECT CONCAT(courseName," -- ",courseType) "concat",CONCAT_WS(" <-> ",courseName,courseWeek,courseTime) "concat_ws" FROM course;

例3:字符串的替换

  • 在MySQL中字符串的下标是从1开始的
SELECT INSERT("mysql,oracle,sqlserver",1,5,"PostgreSQL"),REPLACE("mysql,oracle,sqlserver","oracle","MariaDB") ;

例4:字符串的填充

SELECT LPAD("wql",6,"*"),RPAD("wql",6,"*");

例5:字符串的修整

SELECT LTRIM(" w ql "),RTRIM(" w ql "),TRIM(" w ql "),TRIM("w" FROM "wwqlw"),TRIM(LEADING "w" FROM "wwqlw"),TRIM(TRAILING "w" FROM "wwqlw");

例6:字符串的截取

SELECT SUBSTR("hello",3,2),LOCATE("ll","hello"),SUBSTR("hello",LOCATE("ll","hello"),2);

四,日期和时间函数

一,获取日期和时间

函数 用法
CURDATE() ,CURRENT_DATE() 返回当前日期,只包含年,月,日
CURTIME(), CURRENT_TIME() 返回当前时间,只包含时,分,秒
NOW() / SYSDATE() / CURRENT_TIMESTAMP() / LOCALTIME() / LOCALTIMESTAMP() 返回当前系统时间
UTC_DATE() 返回UTC(世界标准时间)日期
UTC_TIME() 返回UTC(世界标准时间)时间
例:
SELECT CURDATE(),CURRENT_DATE(),CURTIME(),CURRENT_TIME(),NOW(),SYSDATE(),CURRENT_TIMESTAMP(),UTC_DATE(),UTC_TIME(),UTC_TIMESTAMP();

二,日期与时间戳的转换

函数 用法
UNIX_TIMESTAMP() 以UNIX时间戳的形式返回当前时间
UNIX_TIMESTAMP(date) 将时间data以UNIX时间戳的形式返回
FROM_UNIXTIME(timestamp) 将UNIX时间戳的时间转换为普通格式的时间
例:
SELECT UNIX_TIMESTAMP(),FROM_UNIXTIME(1652344306),UNIX_TIMESTAMP("2022-5-1 4:45:4");

三,获取月份,星期,星期数,天数等函数

函数
用法
YEAR(date) / MONTH(date) / DAY(date)
返回具体的日期值
HOUR(time) / MINUTE(time) / SECOND(time)
返回具体的时间值
MONTHNAME(date)
返回月份:January……
DAYNAME(date)
返回星期几:MONDAY,TUESDAY……SUNDAY
WEEKDAY(date)
返回周几,注:周一是0,周2是1,。。。周日是6
QUARTER(date)
返回日期对应的季度,范围为1~4
WEEK(date) , WEEKOFYEAR(date)
返回一年中的第几周
DAYOFYEAR(date)
返回日期是一年中的第几天
DAYOFMONTH(date)
返回日期位于所在月份的第几天
DAYOFWEEK(date)
返回周几
注:
  • date可以通过CURDATE(),NOW(),CURRENT_DATE(),LOCALTIMESTAMP()等方式获取
  • time可以通过CURTIME(), CURRENT_TIME(),,NOW(),LOCALTIMESTAMP()等方式获取
例:
SELECT YEAR(CURDATE()) "年",MONTHNAME(CURDATE()) "月份",WEEK(CURDATE()) "第几周",WEEKDAY(CURDATE()) "周几",DAYNAME(CURDATE()) "星期几",DAYOFYEAR(CURDATE()) "一年中的第几天",HOUR(CURTIME()) "小时",MINUTE(CURTIME()) "分钟",SECOND(CURTIME()) "秒";

四,日期的操作函数

函数 用法
EXTRACT(type FROM date) 返回指定日期中特定的部分,type指定返回的值

EXTRACT函数中type的取值与含义:

例:

SELECT EXTRACT(DAY FROM NOW()) "当月份的第几天",EXTRACT(WEEK FROM CURDATE()) "第几个星期";

五,时间和秒转化的函数

函数 用法
TIME_TO_SEC(time) 将time转化为秒并返回结果集,转化公式:小时*3600+分钟*60+秒
SEC_TO_TIME(seconds) 将seconds描述转化为包含小时,分钟,秒的普通时间公式
 
例:
SELECT TIME_TO_SEC(NOW()) ,SEC_TO_TIME(65410);

六,计算日期时间的函数

函数 用法
DATE_ADD(datetime,INTERVAL expr type)

ADDDATE(date,INTERVAL expr type)

返回与给定日期时间相差INTERVAL时间段的日期时间
DATE_SUB(date,INTERVAL expr type)

SUBDATE(date,INTERVAL expr type)

返回与date相差INTERVAL时间间隔的日期

注:DATE_ADD和DATE_SUB实际使用是一样的

type的取值:

例:

SELECT NOW(),DATE_ADD(NOW(),INTERVAL 1 YEAR),DATE_ADD(NOW(),INTERVAL -1 YEAR),DATE_SUB(NOW(),INTERVAL 1 YEAR),DATE_SUB(NOW(),INTERVAL -1 YEAR);

其他:

函数
用法
ADDTIME(time1,time2)
返回time1加上time2的时间,当time2为一个数字时,代表的是秒,可以为负数
SUBTIME(time1,time2)
返回time1减去time2后的时间。当time2为一个数字时,代表的是秒,可以为负数
DATEDIFF(date1,dete2)
返回date1 - date2的日期间隔天数
TIMEDIFF(time1,time2)
返回time1 - time2的时间间隔
FROM_DAYS(N)
返回从0000年1月1日起,N天以后的日期
TO_DAYS(date)
返回日期date距离0000年1月1日的天数
LAST_DAY(date)
返回date所在月份的最后一天的日期
MAKEDATE(year,n)
针对给定年份与所在年份的天数返回一个日期
PERIOD_ADD(time,n)
返回time加上n后的时间
例:

例:

SELECT ADDTIME(NOW(),100),SUBDATE(NOW(),2),MAKEDATE(YEAR(NOW()),12);

七,日期的格式化与解析

  MySQL默认有隐式的日期转换,但只适应于"Y-M-D H:m:S"的格式,如果字符串性的日期格式不是这种格式就无法进行隐式转换,这个时候就需要自定义的日期格式化

函数 用法
DATE_FORMAT(date,fmt) 按照字符串fmt格式化date值
TIME_FORMAT(time,fmt) 按照字符串fmt格式化时间time值
GET_FORMAT(date_type,format_type) 返回日期字符串的显示格式
STR_TO_DATE(str,fmt) 按照字符串fmt对str进行解析,解析为一个日期
上述非中fmt参数常用的格式符:GET_FORMAT函数不适应用
格式符
说明
格式符
说明
%Y
4位数字表示年份
%y
两位数字年份
%M
月份名表示月份(January……)
%m
两位数字表示月份(01,02,03……)
%b
缩写的月名表示月份(Jan,Feb…)
%c
数字表示月份
%D
英文后缀表示月中的天数(lst,2nd,3rd)
%d
两位数字表示月中的天数(01,02……)
%e
数字表示月中的天数(1,2,3……)
%H
两位数字表示小时,24小时制
%h或%l
两位数字表示小时,12小时制
%k
数字形式表示小时,24小时制
%l
数字形式表示小时,12小时制
%i
两位数字表示分钟(00,01,02……)
%S和%s
两位数字表示分秒(00,01,02……)
%W
一周中星期的名称(Sunday……)英文名
%a
一周中星期的名称(Sun,Mon……)英文缩写

例1:普通格式化

SELECT CURDATE(),DATE_FORMAT(CURDATE(),"%y<->%M<->%D"),CURTIME(),TIME_FORMAT(CURTIME(),"%h~%i~%s");

例2:逆向解析(将自定义格式转化位通用date格式)

SELECT STR_TO_DATE("22<->May<->12th","%y<->%M<->%D");

五,流程控制函数

 流程处理函数可以根据不同的条件,执行不同的处理流程,可以在SQL语句中实现不同的条件选择,MySQL中的流程处理函数主要包括IF(),IFNULL()和CASE()函数

函数 用法
IF(value,value1,value2) 如果value的值为TRUE,返回value1,否则返回value2
IFNULL(value1,value2) 如果value1不为NULL,返回value1,否则返回value2
CASE WHEN 条件1 THEN 结果1 WHEN条件2 THEN结果2 …[ELSE resulth] END 相当于JAVA的if…else if…else……
CASE 字段 WHEN 常量值1 HEN 结果1 WHEN 常量值2 THEN结果2 …[ELSE resulth] END 相当于JAVA的switch…case…

 例1:if

SELECT category_className "书名",IF(category_id IN(2),"童书馆所属","非童书") "所属" FROM category_class;

例2:ifnull

SELECT bookname '书名',author '作者',IFNULL(date,"无出版时间") "出版时间" FROM book;

例3:case 常量

SELECT category_className "书名",CASE category_id
    WHEN 1 THEN "文学综合馆"
    WHEN 2 THEN "童书馆"
    WHEN 3 THEN    "教育馆"
    WHEN 4 THEN "人文社科馆"
    WHEN 5 THEN "经管综合馆"
    ELSE "无所属馆"
END "所属馆"
FROM category_class;

六,加密和解密函数

加密和解密函数主要用于对数据库中的数据进行安全处理,以防止数据被他窃取。MySQL提供了函数进行操作

函数 用法
PASSWORD(str) 返回字符串str的加密版本,41位长的字符串。加密结果不可逆
MD5(str) 返回字符串str的md5加密后的值,也是一种加密方式。若参数为NULL,则会返回NULL
SHA(str) 从原明文密码str计算并返回加密后的密码字符串,当参数为null时,返回null。SHA算法比MD5算法更安全
ENCODE(value,password_seed) 返回使用password_seed做为加密密码加密value
DECODE(value,password_seed) 返回使用password_seed做为解密密码解密value
注:在MySQL8.0版本不支持PASSWORD(str)函数和ENCODE,DNCODE函数

例1:加密 

SELECT PASSWORD("WQL"),MD5("WQL"),SHA("WQL");

例2:加密成密文

SELECT ENCODE("WQL","fq"),DECODE(ENCODE("WQL","fq"),"fq");

七,MySQL信息函数和其他函数

一,MySQL信息函数

MySQL中内置了一些可以查询MySQL系统信息的函数,这些可以帮助数据库开发人员更好的对数据库进行维护

函数 作用
VERSION() 返回当前MySQL的版本号
CONNECTION_ID() 返回当前MySQL服务器的连接数
DATABASE(),SCHEMA() 返回MySQL命令行的当前所在的数据库
USER(),CURRENT_USER(),SYSTEM_USER(),SESSION_USER() 返回当前连接MySQL的用户名,返回结果为"主机名@用户名"
CHARSET(value) 返回字符串value自变量的字符集
COLLATION(value) 返回字符串value的比较规则
注:一般分库的条件是看当前数据库访问的可用连接数是否不足

例:

SELECT VERSION(),CONNECTION_ID(),DATABASE(),USER(),CHARSET("w"),COLLATION("s");

二,其他函数

函数 作用
FORMAT(value,n) 返回对数字value进行格式化的结果数据,n表示四舍五入后保留到小数点后n位
CONV(value,from,to) 将value的值进行不同进制之间的转化(value为原数,from原数的进制,to需要转化的进制)
INET_ATON(ipvalue) 将以点分隔的IP地址转化位一个数字
INET_NTOA(value) 将数字形式的IP地址转化位以点分隔的IP地址
BENCHMARK(n,expr) 将表达式expr重复执行n,用于测试MySQL处理expr表达式所耗费的时间
CONVERT(value USING char_code) 将value所使用的字符编码修改位char_code
注:ip地址转化为数字就是分别分别乘以256的n次方,如:"192.168.68.133" = (192*253^3) + (168*256^2) +(68*256) + 133  

例:

SELECT FORMAT(123.12,1),CONV(100,10,2),INET_ATON("192.168.68.133"),INET_NTOA(3232253061),BENCHMARK(4,SHA("fq"));

八,聚合函数

聚合函数作用于一组数据,并对该组数据进行汇总,最后返回一个值

基础的聚合函数有五个:

  1. AVG():求平均值
  2. SUM():求和
  3. MAX():最大值
  4. MIN():最小值
  5. COUNT():统计记录

AVG() = SUM() / COUNT()

例1:简单演示

SELECT AVG(id),SUM(id),COUNT(id),MAX(id),MIN(id) FROM news;

COUNT()的写法:

  • COUNT(字段名):通过字段值进行计数,一个值就+1,n个值就+n
  • COUNT(常数):把该表的行以该常数代替,有n个常数就加n
  • COUNT(*):和常数的方式差不多

  COUNT(字段名)的方式在实际应用中有很大的问题,COUNT本身是忽略null的,假如字段有很多null是不加入计数的,如:现在表有100条数据,通过num字段进行计数且该字段有20个空值,那么count(num)=80,这种方式是不合理的

解决忽略null问题的方法:

  1. 通过COUNT(常数)和COUNT(*)的方式进行计数
  2. COUNT(IFNULL(字段名,常数)):通过ifnull判断字段值是否为空,假如为空就用常数代替

SUM()求和也是忽略空值的,但在实际应用中没有啥关系

  AVG()也是忽略空值的,通过这个函数求平均值也有null值问题,它的底层是通过sum()/count(),如:求全国的平均工资,假如有1亿人没有就业,工资为null,那么这一亿人在avg()中就不参与计算,这是不合理的

AVG()解决空值问题:

  • AVG(IFNULL(字段,常数))

演示:现在有一张表test

例2:出现null问题

SELECT AVG(number),SUM(number),COUNT(number),SUM(number)/COUNT(number)FROM test;

例3:解决null问题

SELECT AVG(IFNULL(number,1)),SUM(number),COUNT(1),COUNT(*),SUM(number)/COUNT(IFNULL(number,1)) FROM test;