MySQL-存储过程
我们常用的操作数据库语言SQL语句在执行的时候需要要先编译, 然后执行; 而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集, 经编译后存储在数据库中, 用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。
一个存储过程是一个可编程的函数, 它在数据库中创建并保存。它可以有SQL语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的函数, 或者封装特定功能时, 存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟。它允许控制数据的访问方式。可以认为是用来重复执行的一系列SQL语句(类似函数)。
优点: 如果一系列SQL语句, 被用来多次执行, 那么用存储过程是很快的。因为存储过程是预编译的。在首次运行一个存储过程时查询, 优化器对其进行分析优化, 并且给出最终被存储在系统表中的执行计划。而批处理的Transaction-SQL语句在每次运行时都要进行编译和优化, 速度相对要慢一些。
先讲解变量:
MySQL中变量以"@"开始 形式为"@变量名" 使用set、select配合":="、"="来进行设置或赋值 比如"set @name='John'", "set @name:='John'", "select @mid:=max(id) from tname"类似来设置变量 set可以用":=", 也可以用"=", 但select只能用":=" 因为select语句中"="表示相等判断
系统变量: 服务器运行时许多变量可以动态更改,而无需重启服务器,即动态配置。设置用户变量的时候加上GLOBAL等就是设置系统变量 可以使用"set GLOBAL 变量名"或者"set @@global.变量名"来设置系统变量 系统变量对所有客户端有效 只有超级权限的用户才可以设置系统变量 引用的时候只能用@@
用户变量/会话变量: 基于会话变量实现的,可以暂存值,并传递给同一连接里的下一条sql使用的变量。经常用来向SQL中传值。当客户端连接退出时,变量会被释放。设置用户变量时没有加上GLOBAL等就是设置会话变量 即使用默认的SESSION(LOCAL) 可以使用"set @变量名"、"set SESSION 变量名"、"set @@session.变量名" 是跟客户端绑定的 设置的变量只对连接的客户端有效 客户端关闭后变量消失
局部变量: 在BEGIN、END语句块之间设置的变量
局部变量和用户变量区分在于三点:
1.定义语句不同,用户变量使用set定义,局部变量使用declare定义;
2.用户变量是以"@"开头的,而局部变量没有这个符号;
3.作用范围,用户变量作用于本客户端,局部变量作用于本块;
@@var_name如果不指定global|local|session, 则返回session中的值, 否则返回global的值 实用原则: 普通变量用@, 系统变量用@@
总结: 变量包括系统变量、会话变量和局部变量(只要记住有这三种类型变量及其区分就行了), 且变量的只只能为单一值(比如count(*)), 不能为查询出来的多条记录
查询变量的值: "select @name"、"select @@global.GROUP_CONCAT_MAX_LEN"、"select @@GROUP_CONCAT_MAX_LEN"(查询的session的)
只要不加global 默认都是session
注: BEGIN、END可以认为是函数中的花括号"{"、"}", 以包含函数体或者结构块;
创建:
CREATE PROCEDURE 存储过程名(参数列表)
BEGIN
SQL语句(比如 "SELECT * INTO s FROM USERS;"); #语句以分号结束
END
注: 可以用"DELIMITER //"来设置MySQL的语句结束符号 记得改完再改回来
参数类型有三种IN(输入参数, 在调用存储过程时指定, 相当于PHP的值传递), OUT(输出参数, 可返回, 相当于PHP的引用传值, 不论用户传值与否初始都为NULL), INOUT(输入输出参数)
删除:
DROP PROCEDURE 存储过程名
修改:
ALTER PROCEDURE 存储过程名(参数列表)
语句块
查询:
SHOW CREATE PROCEDURE 数据库名.存储过程名 //查看存储过程的详细
SHOW PROCEDURES STATUS //查看所有或者某个数据库下的存储过程 后也可以跟where db='数据库名' 指定数据库;
调用:
CALL 存储过程名(参数列表)
注: CALL语句可以用声明为OUT或的INOUT参数的参数给它的调用者传回值 存储过程名称后面必须加括号 哪怕该存储过程没有参数传递
注释:
1.使用"--" 单行注释
2.使用"/**/" 多行注释
DECLARE语句用来声明局部变量, 仅被用在BEGIN, END复合语句里, 且必须在复合语句的开头, 任何其他语句之前 句式为DECLARE variable_name [,variable_name...] datatype [DEFAULT value];
示例: DECLARE l_int int unsigned default 4000000;(跟创建表结构时一样)
SELECT INTO语句来对变量进行赋值 select user, pass into x, y from user; 变量名不能与列名相同!!
存储过程参数:
参数变量以及里面DECLARE的变量都不用@
MySQL 存储过程参数(in)
MySQL 存储过程 "in" 参数:跟 C 语言的函数参数的值传递类似, MySQL 存储过程内部可能会修改此参数,但对 in 类型参数的修改,对调用者(caller)来说是不可见的(not visible)
MySQL 存储过程参数(out)
MySQL 存储过程 "out" 参数:从存储过程内部传值给调用者 在存储过程内部, 该参数初始赋值为null, 无论调用者调用存储过程时是否给此参数设置值
MySQL 存储过程参数(inout)
MySQL 存储过程 inout 参数跟C语言的引用传递类似 可以从存储过程内部传值给调用者 不同的是:调用者还可以通过 inout 参数传递值给存储过程
总结: 如果仅仅想把数据传给 MySQL 存储过程,那就使用"in" 类型参数;如果仅仅从 MySQL 存储过程返回值,那就使用"out" 类型参数;如果需要把数据传给 MySQL 存储过程,还要经过一些计算后再传回给我们,此时,要使用"inout" 类型参数
示例:
create procedure my_pro(in n int)
begin
select @name:=User from user where id=n limit 1;
end;
调用:
set @n=1
call my_pro(@n);
结构语句:
if vname='John' then
...
else
...
end if;
case vname
when 0 then
...
when 1 then
...
else
...
end case;
while vname < 6 do
...
end while;
字符串类函数:
CHARSET(str) //返回字串字符集
CONCAT (string2 [,... ]) //连接字串
INSTR (string ,substring ) //返回substring首次在string中出现的位置,不存在返回0
LCASE (string2 ) //转换成小写
LEFT (string2 ,length ) //从string2中的左边起取length个字符
LENGTH (string ) //string长度
LOAD_FILE (file_name ) //从文件读取内容
LOCATE (substring , string [,start_position ] ) 同INSTR,但可指定开始位置
LPAD (string2 ,length ,pad ) //重复用pad加在string开头,直到字串长度为length
LTRIM (string2 ) //去除前端空格
REPEAT (string2 ,count ) //重复count次
REPLACE (str ,search_str ,replace_str ) //在str中用replace_str替换search_str
RPAD (string2 ,length ,pad) //在str后用pad补充,直到长度为length
RTRIM (string2 ) //去除后端空格
STRCMP (string1 ,string2 ) //逐字符比较两字串大小,
SUBSTRING (str , position [,length ]) //从str的position开始,取length个字符,
注:mysql中处理字符串时,默认第一个字符下标为1,即参数position必须大于等于1
数学类函数:
ABS (number2 ) //绝对值
BIN (decimal_number ) //十进制转二进制
CEILING (number2 ) //向上取整
CONV(number2,from_base,to_base) //进制转换
FLOOR (number2 ) //向下取整
FORMAT (number,decimal_places ) //保留小数位数
HEX (DecimalNumber ) //转十六进制
注:HEX()中可传入字符串,则返回其ASC-11码,如HEX('DEF')返回4142143
也可以传入十进制整数,返回其十六进制编码,如HEX(25)返回19
LEAST (number , number2 [,..]) //求最小值
MOD (numerator ,denominator ) //求余
POWER (number ,power ) //求指数
RAND([seed]) //随机数
ROUND (number [,decimals ]) //四舍五入,decimals为小数位数]
时间类函数:
ADDTIME (date2 ,time_interval ) //将time_interval加到date2
CONVERT_TZ (datetime2 ,fromTZ ,toTZ ) //转换时区
CURRENT_DATE ( ) //当前日期
CURRENT_TIME ( ) //当前时间
CURRENT_TIMESTAMP ( ) //当前时间戳
DATE (datetime ) //返回datetime的日期部分
DATE_ADD (date2 , INTERVAL d_value d_type ) //在date2中加上日期或时间
DATE_FORMAT (datetime ,FormatCodes ) //使用formatcodes格式显示datetime
DATE_SUB (date2 , INTERVAL d_value d_type ) //在date2上减去一个时间
DATEDIFF (date1 ,date2 ) //两个日期差
DAY (date ) //返回日期的天
DAYNAME (date ) //英文星期
DAYOFWEEK (date ) //星期(1-7) ,1为星期天
DAYOFYEAR (date ) //一年中的第几天
EXTRACT (interval_name FROM date ) //从date中提取日期的指定部分
MAKEDATE (year ,day ) //给出年及年中的第几天,生成日期串
MAKETIME (hour ,minute ,second ) //生成时间串
MONTHNAME (date ) //英文月份名
NOW ( ) //当前时间
SEC_TO_TIME (seconds ) //秒数转成时间
STR_TO_DATE (string ,format ) //字串转成时间,以format格式显示
TIMEDIFF (datetime1 ,datetime2 ) //两个时间差
TIME_TO_SEC (time ) //时间转秒数]
WEEK (date_time [,start_of_week ]) //第几周
YEAR (datetime ) //年份
DAYOFMONTH(datetime) //月的第几天
HOUR(datetime) //小时
参考:http://www.blogjava.net/sxyx2008/archive/2009/11/24/303497.html
参考:http://www.jb51.net/article/30825.htm