mysql中常用函数与存储过程的创建
- 常用函数汇总
- 数学函数
- 字符串函数
- 日期和时间函数
- 条件判断函数
- 系统函数
- 加密函数
- 其他函数
- 自定义函数
- 自定义变量的声明和赋值
- 基本语法
- 实例
- 存储过程
- 事务
- 基本语法
- 实例
- 函数和存储过程的区别
mysql作为一款开源的免费关系型数据库,用户基础非常庞大,本文列出了mysql常用函数以及自定义函数和存储过程的创建与使用,方便大家随时查看使用这些函数,可以极大地提高用户对于数据库的管理效率,从而更加灵活地满足不同用户的需求。
常用函数汇总
- 概念:
相当于java中的方法,将一组逻辑语句封装在方法体中,对外暴露方法名
- 隐藏了实现细节
- 提高代码的可重用性
- 使用:
select 函数名(实参列表)【from 表】 【】中内容可省略
数学函数
- mod(x,y) 取余 :y=0时返回x的值
SELECT MOD(10,3); # 输出 1
SELECT MOD(10,-3); # 输出 1
- ceil(float) 进1: 向上取整,返回>=该参数的最小整数
SELECT CEIL(1.5); # 输出 2
SELECT CEIL(-1.5); # 输出 -1
- floor(float) 舍1:向下取整,返回<=该参数的最大整数
SELECT FLOOR(1.5); # 输出 1
SELECT FLOOR(-1.5); # 输出 -2
- round(float[,n]) n小数精度,四舍五入
SELECT round(1.5) # 输出 2
SELECT round(-1.5) # 输出 -2 该四舍五入计算方式为:绝对值四舍五入加负号
- truncate(num,n) 截取num的小数为n位
SELECT TRUNCATE(3.1415926,2); # 输出 3.14
- ABS(x) :返回x的绝对值
- PI():返回圆周率π,默认显示6位小数
- SQRT(x) :返回非负数的x的二次方根
- SIGN(x):返回参数x的符号,-1表示负数,0表示0,1表示正数
- POW(x,y)和POWER(x,y):返回x的y次乘方的值
- EXP(x):返回e的x乘方后的值
- LOG(x):返回x的自然对数,x相对于基数e的对数
- LOG10(x):返回x的基数为10的对数
- RADIANS(x):返回x由角度转化为弧度的值
- DEGREES(x):返回x由弧度转化为角度的值
- SIN(x)、ASIN(x):前者返回x的正弦,其中x为给定的弧度值;后者返回x的反正弦值,x为正弦
- COS(x)、ACOS(x):前者返回x的余弦,其中x为给定的弧度值;后者返回x的反余弦值,x为余弦
- TAN(x)、ATAN(x):前者返回x的正切,其中x为给定的弧度值;后者返回x的反正切值,x为正切
- COT(x):返回给定弧度值x的余切
字符串函数
- length(varchar):返回字符串的字节长度(utf-8 一个汉字为3个字节,gbk为2个字节)
SELECT LENGTH('cbuc') # 输出 4
SELECT LENGTH('蔡不菜cbuc') # 输出13
- char_length(varchar):返回字符串的长度
SELECT CHAR_LENGTH('cbuc') # 输出 4
SELECT CHAR_LENGTH('蔡不菜cbuc') # 输出7
- concat(str1,str2,…) :拼接字符串
SELECT CONCAT('C','_','BUC') # 输出 C_BUC
- concat_ws(joinStr,str1,str2,…) :连接字符串(返回多个字符串拼接之后的字符串,每个字符串之间有一个x)
- lower(str)/upper(str):大小写转换
SELECT UPPER('cbuc') # 输出 CBUC
SELECT LOWER('CBUC') # 输出 cbuc
- left(str1,n)/right(str1,n)/mid(str1,startPos,n):截取字符串(前者返回字符串str1从最左边开始的n个字符,中间返回字符串str1从最右边开始的n个字符,后者返回字符串str1从starPos位置(包含)开始截取数量为n的字符串)
- substr / substring:裁剪字符串
substr(str,pos) # str:要裁剪的字符串 , pos:要裁剪的长度
substr(str,pos,len) # str:要裁剪的字符串 , pos/len:从哪个位置开始裁剪几位
# substring同理
- instr(str1,deststr) :返回deststr在str1中第一次出现的位置(从1开始,不存在返回0)
SELECT INSTR('蔡不菜','蔡') # 输出 1 (mysql是从1开始算位数)
- reverse(str):字符串反转
- trim():字符串去除字符,ltrim(s)、rtrim(s):前者返回字符串s,其左边所有空格被删除;后者返回字符串s,其右边所有空格被删除
SELECT TRIM(' cbuc ') # 输出 cbuc
SELECT TRIM('a' from 'aaaacbucaaaa') #输出 cbuc
- lpad/rpad(str1,n,str2) :左右填充字符char,str1.length>len,被截取,否则填充
SELECT LPAD('cbuc',6,'*') # 输出 **cbuc
SELECT RPAD('cbuc',6,'*') # 输出 cbuc**
- replace(s,s1,s2):返回一个字符串,用字符串s2替代字符串s中所有的字符串s1
SELECT REPLACE('小菜爱睡觉','睡觉','吃饭') # 输出 小菜爱吃饭
- insert(s1,x,len,s2):返回字符串s1,其子字符串起始于位置x,被字符串s2取代len个字符
- repeats,n): 返回一个由重复字符串s组成的字符串,字符串s的数目等于n
- space(n):返回一个由n个空格组成的字符串
- strcmp(s1,s2):若s1和s2中所有的字符串都相同,则返回0;根据当前分类次序,第一个参数小于第二个则返回-1,其他情况返回1
日期和时间函数
- 返回当前系统时间: now() (“YYYY-MM-DD HH:MM:SS”)/curdate() (“YYYY-MM-DD”) /curtime() (“HH:MM:SS”)
now:返回当前系统日期+时间
SELECT NOW() # 输出 2020-02-16 11:43:21
curdate:返回当前系统日期,不包含时间
SELECT CURDATE() # 输出 2020-02-16
curtime:返回当前时间,不包含日期
SELECT CURTIME() # 输出 11:45:35
- DAYOFWEEK(date):表示返回日期date是星期几,记住:星期天=1,星期一=2,… 星期六=7
- WEEKDAY(date):表示返回date是在一周中的序号,西方日历中通常一周的开始是星期天,并且以0开始计数,所以,记住:0=星期一,1=星期二, … 5=星期六
- DAYOFMONTH(date):表示返回date是当月的第几天,1号就返回1,… ,31号就返回31
- DAYOFYEAR(date):表示返回date是当年的第几天,01.01返回1,… ,12.31就返回365
- MONTH(date):表示返回date是当年的第几月,1月就返回1,… ,12月就返回12
- DAYNAME(date):表示返回date是周几的英文全称名字
- MONTHNAME(date):表示返回date的是当年第几月的英文名字
- QUARTER(date):表示返回date的是当年的第几个季度,返回1,2,3,4
- WEEK(date,index):该函数返回date在一年当中的第几周,date(01.03)是周日,默认是以为周日作为一周的第一天,函数在此处返回1可以有两种理解:1. 第一周返回0,第二周返回1,… ,2. 以当年的完整周开始计数,第一周返回1,第二周返回2,… ,最后一周返回53
- YEAR(date):表示返回date的4位数年份。要注意的是:如果年份只有两位数,那么自动补全的机制是以默认时间1970.01.01为界限的,>= 70 的补全 19,< 70 的补全 20
- HOUR(time):返回该date或者time的hour值,值范围(0-23)
- MINUTE(time):返回该time的minute值,值范围(0-59)
- SECOND(time):返回该time的minute值,值范围(0-59)
- PERIOD_ADD(month,add):该函数返回对month做增减的操作结果,month的格式为yyMM或者yyyyMM,返回的都是yyyyMM格式的结果,add可以传负值
- PERIOD_DIFF(monthStart,monthEnd):该函数返回monthStart - monthEnd的间隔月数
- DATE_ADD(date,INTERVAL number type),同 ADDDATE():DATE_ADD()和ADDDATE()返回对date操作的结果
- date的格式可以是“15-12-31”,可以是“15-12-31 23:59:59”,也可以是“2015-12-31 23:59:59”,如果参数date是date格式,则返回date格式结果,如果参数date是datetime格式,则返回datetime格式结果
- type格式:
SECOND 秒 SECONDS
MINUTE 分钟 MINUTES
HOUR 时间 HOURS
DAY 天 DAYS
MONTH 月 MONTHS
YEAR 年 YEARS
MINUTE_SECOND 分钟和秒 “MINUTES:SECONDS”
HOUR_MINUTE 小时和分钟 “HOURS:MINUTES”
DAY_HOUR 天和小时 “DAYS HOURS”
YEAR_MONTH 年和月 “YEARS-MONTHS”
HOUR_SECOND 小时, 分钟, “HOURS:MINUTES:SECONDS”
DAY_MINUTE 天, 小时, 分钟 “DAYS HOURS:MINUTES”
DAY_SECOND 天, 小时, 分钟, 秒 “DAYS HOURS:MINUTES:SECONDS” - 另外,如果不用函数,也可以考虑用操作符“+”,“-”。
- DATE_SUB(date,INTERVAL number type),同 SUBDATE():用法和DATE_ADD()与ADDDATE()类似,一个是加,一个是减,用时参照16点,具体用法请参考DATE_ADD()与ADDDATE()。
- TO_DAYS(date):返回西元0年至日期date是总共多少天
- FROM_DAYS(date):返回西元0年至今多少天的DATE值
- DATE_FORMAT(date,format):根据参数对date进行格式化。
format的格式都列出来:
%M 月名字(January……December)
%W 星期名字(Sunday……Saturday)
%D 有英语前缀的月份的日期(1st, 2nd, 3rd, 等等。)
%Y 年, 数字, 4 位
%y 年, 数字, 2 位
%a 缩写的星期名字(Sun……Sat)
%d 月份中的天数, 数字(00……31)
%e 月份中的天数, 数字(0……31)
%m 月, 数字(01……12)
%c 月, 数字(1……12)
%b 缩写的月份名字(Jan……Dec)
%j 一年中的天数(001……366)
%H 小时(00……23)
%k 小时(0……23)
%h 小时(01……12)
%I 小时(01……12)
%l 小时(1……12)
%i 分钟, 数字(00……59)
%r 时间,12 小时(hh:mm:ss [AP]M)
%T 时间,24 小时(hh:mm:ss)
%S 秒(00……59)
%s 秒(00……59)
%p AM或PM
%w 一个星期中的天数(0=Sunday ……6=Saturday )
%U 星期(0……52), 这里星期天是星期的第一天
%u 星期(0……52), 这里星期一是星期的第一天
%% 字符% ) - TIME_FORMAT(time,format):
具体用法和DATE_FORMAT()类似,但TIME_FORMAT只处理小时. 分钟和秒(其余符号产生一个NULL值或0)
条件判断函数
备注:[… ] 代表可选操作,下面与java进行对比
- 运算符
- if(condition,v1,v2)
+condition=true,执行v1,否则执行v2 - ifnull(v1,v2)
相当于if(v1=null,v2,v1) - case expr when v1 then r1 [when v2 then v2…] [else rn] end case
相当于switch-case - if condition1 then statement_list1 [elseif condition2 then statement_list2] […][else statement_list3] end if
相当于多重if
- 循环
- [begin_label:] loop statement_list end loop [end_label]
通常需在statement_list中指定退出条件,否则为死循环。 - [begin_label:] while condition do statement_list end while [end_label]
相当于do-while - [begin_label:] repeat statement_list until condition end repeart [end_label]
相当于while
- 退出语句
- LEAVE label
相当于break - ITERATE label
相当于continue
系统函数
- version() 查看mysql版本号
- connection_id() 查看当前用户的连接数
- user()/current_user()/system_user()/session_user() 查看当前被mysql服务器验证的用户名和主机的组合,一般这几个函数的返回值是相同的
- charset(str) 查看字符串str使用的字符集
- collation() 查看字符串排列方式
加密函数
- password(field/str)
从原明文密码str计算并返回加密后的字符串密码,注意这个函数的加密是单向的(不可逆),因此不应将它应用在个人的应用程序中而应该只在MySQL服务器的鉴定系统中使用 - md5(concat(‘prefix’,field/str,‘suffix’))
为字符串算出一个MD5 128比特校验和,改值以32位十六进制数字的二进制字符串形式返回 - encode/decode(str,pass_str) 使用pswd_str作为密码,加密/解密str
其他函数
- cast(field/val as type)类型转换
type类型受限:
signed/unsigned [integer]
decimal - conv(n,from_base,to_base)
不同进制数之间的转换,返回值为数值n的字符串表示,由from_base进制转换为to_base进制 - format(x,n)
将数字x格式化,并以四舍五入的方式保留小数点后n位,结果以字符串形式返回
自定义函数
自定义变量的声明和赋值
在学习自定义函数和存储过程的前提,必须掌握自定义变量的创建,下面我先简述一下mysql中两种自定义变量的声明和复制。
- 方法一(只能在方法体中使用)
- 声明:declare varname DATA_TYPE [default value];
- 赋值:select … into varname;
- 方法二
- 声明:set @varname = value[,…];
- 赋值:select @varname:=FIELD/count(1)…from…where…
基本语法
自定义函数 (user-defined function UDF)就是用一个象ABS() 或 CONCAT()这样的固有(内建)函数一样作用的新函数去扩展MySQL。所以UDF是对MySQL功能的一个扩展。
- 显示函数
show function status; - 显示创建函数信息
show create function FUNC_NAME; - 创建语法结构
create function func([PARAMS PARAMS_TYPE,…]) returns RETURN_TYPE
begin
…
return…
end; - 删除函数
drop function [if exists] FUNC_NAME;
实例
- 执行addSubject()函数向subjectinfo表增加一条记录
delimiter //
drop function if exists addSubject;
//
create function addSubject(_proId int,_subName varchar(20),_classHours int) returns int
begin
declare num int default 0;
insert into subjectinfo(proId,subName,classHours) values
(_proId,_subName,_classHours);
select count(id) from subjectinfo where subName=_subName into num;
return num;
end;
//
set @proId=3,@subName='elasticsearch',@classHours=88,@rtn=0;
select @rtn:=addSubject(@proId,@subName,@classHours);
select @rtn;
//
- 运行结果
Query OK, 0 rows affected (0.00 sec)
+-----------------------------------------------+
| @rtn:=addSubject(@proId,@subName,@classHours) |
+-----------------------------------------------+
| 1 |
+-----------------------------------------------+
1 row in set (0.01 sec)
+------+
| @rtn |
+------+
| 1 |
+------+
1 row in set (0.01 sec)
- 查询subjectinfo表记录
mysql> select * from subjectinfo;
+----+-------+----------------------+------------+
| id | proId | subName | classHours |
+----+-------+----------------------+------------+
| 1 | 1 | KB Java逻辑 | 34 |
| 2 | 1 | KB JavaOOP | 72 |
| 3 | 1 | KB Java高级特性 | 57 |
| 4 | 1 | KB HTML | 43 |
| 5 | 1 | KB CSS | 36 |
| 6 | 1 | KB JS | 64 |
| 7 | 1 | KB JQuery | 43 |
| 8 | 1 | KB MySql | 59 |
| 9 | 1 | KB JDBC | 48 |
| 10 | 3 | mathsearch | 88 |
+----+-------+----------------------+------------+
49 rows in set (0.00 sec)
存储过程
mysql中存储过程往往和事务分不开的,首先我们先了解一下事务。
事务
- 事务简介
- 定义:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户开户业务,该业务就是一个最小的工作单元)。一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成。事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同
- 事务四大特征(ACID)
原子性(A):事务是最小单位,不可再分
一致性(C):事务要求所有的DML语句操作的时候,必须保证同时成功或者同时失败
隔离性(I):事务A和事务B之间具有隔离性
持久性(D):是事务的保证,事务终结的标志(内存的数据持久到硬盘文件中) - 关于事务的一些术语
开启事务:Start Transaction
事务结束:End Transaction
提交事务:Commit Transaction
回滚事务:Rollback Transaction - 事务开启和结束的标志
- 开启标志:
任何一条DML语句(insert、update、delete)执行,标志事务的开启 - 结束标志(提交或者回滚):
- 提交:成功的结束,将所有的DML语句操作历史记录和底层硬盘数据来一次同步
- 回滚:失败的结束,将所有的DML语句操作历史记录全部清空
- 事务基本语法
- set autocommit=0; 开启事务
- mysql事务锁的分类
- select …; 快照查询,无锁
- select … lock in share mode; 共享锁,在非修改模式下互不影响
- select … for update; 排他锁,只要有其他的共享或排他锁未释放就无法执行
- insert/delete/update … 行级排他锁
- commit/rollback; 提交/回滚事务,保证业务的完整性
基本语法
- 显示事务
show procedure status; - 显示创建事务信息
show create procedure PROC_NAME; - 创建语法结构
1. create procedure proname([in PARAMS PARAMS_TYPE,…,on PARAMS PARAMS_TYPE…])
begin
[start transaction;]
…
[commit/rollback;]
end;
- 调用事务
call proname(); - 删除事务
drop procedure [if exists] PROC_NAME;
实例
- 执行proAddEmpclass,向empclassinfo新增记录
delimiter //
drop procedure proAddEmpclass;
//
create procedure proAddEmpclass(in _empId int,in _classId int,out rtn int)
begin
declare err int default 0;
-- continue 继续 exit 退出
declare continue handler for sqlexception set err=1;
-- 启动事务
start transaction;
insert into empclassinfo(empId,classId,beginDate) values(_empId,_classId,curdate());
set rtn=err;
if err=0 then commit;
else rollback;
end if;
end;
//
set @empId=11,@classId=6,@rtn=0;
call proAddEmpclass(@empId,@classId,@rtn);
select @rtn;
//
- mysql执行结构
mysql> set @empId=11,@classId=6,@rtn=0;
-> call proAddEmpclass(@empId,@classId,@rtn);
-> select @rtn;
-> //
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
+------+
| @rtn |
+------+
| 0 |
+------+
1 row in set (0.01 sec)
- empclassinfo结构
select * from empclassinfo//
+----+---------+-------+------------+
| id | classId | empId | beginDate |
+----+---------+-------+------------+
| 1 | 1 | 1 | 2020-05-11 |
| 2 | 1 | 2 | 2020-08-15 |
| 3 | 2 | 3 | 2020-02-22 |
| 4 | 3 | 2 | 2020-04-16 |
| 5 | 4 | 5 | 2020-04-21 |
| 6 | 5 | 4 | 2019-11-25 |
| 7 | 6 | 2 | 2019-10-08 |
| 8 | 1 | 6 | 2020-05-11 |
| 9 | 2 | 6 | 2020-02-22 |
| 10 | 3 | 7 | 2020-04-16 |
| 11 | 4 | 7 | 2020-04-21 |
| 12 | 5 | 8 | 2019-11-25 |
| 13 | 6 | 8 | 2019-10-08 |
| 14 | 1 | 9 | 2020-05-11 |
| 15 | 2 | 10 | 2020-02-22 |
| 16 | 3 | 9 | 2020-04-16 |
| 17 | 4 | 11 | 2020-04-21 |
| 18 | 5 | 11 | 2019-11-25 |
| 19 | 6 | 10 | 2019-10-08 |
| 21 | 6 | 11 | 2020-07-06 |
| 23 | 6 | 11 | 2020-07-06 |
| 24 | 6 | 11 | 2020-07-08 |
| 25 | 6 | 11 | 2020-07-08 |
| 26 | 6 | 11 | 2020-07-11 |
+----+---------+-------+------------+
24 rows in set (0.00 sec)
函数和存储过程的区别
- 存储过程可以返回多个值,函数只能有一个返回值。
函数是可以嵌入在sql中使用的,可以在select中调用,而存储过程要让sql的query 可以执行, 需要把 mysql_real_connect 的最后一个参数设置为CLIENT_MULTI_STATEMENTS。
函数限制比较多,比如不能用临时表,只能用表变量.还有一些函数都不可用等等.而存储过程的限制相对就比较少。 - 一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。存储过程,功能强大,可以执行包括修改表等一系列数据库操作;用户定义函数不能用于执行一组修改全局数据库状态的操作。
对于存储过程来说可以返回参数,如记录集,而函数只能返回值或者表对象。函数只能返回一个变量;而存储过程可以返回多个。存储过程的参数可以有IN,OUT,INOUT三种类型,而函数只能有IN类,存储过程声明时不需要返回类型,而函数声明时需要描述返回类型,且函数体中必须包含一个有效的RETURN语句。
存储过程,可以使用非确定函数,不允许在用户定义函数主体中内置非确定函数。
存储过程一般是作为一个独立的部分来执行( EXECUTE 语句执行),而函数可以作为查询语句的一个部分来调用(SELECT调用),由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面。 SQL语句中不可用存储过程,而可以使用函数。