Mysql存储过程

存储过程(Stored Procedure):

是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,它存储在数据库中,一次编译后永久有效,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象。

 

存储过程和存储函数

1)一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。存储过程,功能强大,可以执行包括修改表等一系列数据库操作;用户定义函数不能用于执行一组修改全局数据库状态的操作。

2)对于存储过程来说可以返回参数,如记录集,而函数只能返回值或者表对象。函数只能返回一个变量或者表对象;而存储过程可以返回多个。存储过程的参数可以有IN,OUT,INOUT三种类型,而函数只能有IN类~~存储过程声明时不需要返回类型,而函数声明时需要描述返回类型,且函数体中必须包含一个有效的RETURN语句。

3)存储过程,可以使用非确定函数,不允许在用户定义函数主体中内置非确定函数。

4)存储过程一般是作为一个独立的部分来执行( EXECUTE 语句执行),而函数可以作为查询语句的一个部分来调用(SELECT调用),由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面。 SQL语句中不可用存储过程,而可以使用函数。

存储过程:

CREATE PROCEDURE num_from_employee (IN emp_id INT, OUT count_num INT )

存储函数:

CREATE FUNCTION name_from_employee (emp_id INT )

 

存储过程中有个DEFINER

(1) DEFINER的意思是“定义者”,也就是指明此存储过程有哪个用户定义的,它跟存储过程的使用权限无关;可以说,存储和过程是没有使用限制的,任何人都可以使用存储过程,那么为什么还要加上DEFINER指定存储过程的定义者呢,因为,存储过程虽然不限制任何人使用,但是它本身的行为必须受到权限限制,也就是存储过程本身内部具备哪些对数据库的访问权限,而这访问权限便是DEFINER用户对数据库的访问权限。

(2) DEFINER被定义为一个普通的username@hostname用户就不必说了,如果定义为root@%,有什么特别的吗?没有。只不过数据库中要存在root@%用户,否则创建的时候没事,调用的时候就提示root@% is not registered,也就是用户不存在。

(3) DEFINER也可以省略掉,这样存储过程默认的定义者是root@localhost,而一般数据库在安装的时候都会有一个root@localhost用户,所以,该存储过程也能正常在不同的机器上被使用。

5. 既然上述存储过程任何人都以访问,那么它本身运行时的访问权限怎么限制呢。可以通过SQL SECURITY INVOKER ,也就是,其本身的访问权限由调用者权限设置。

6.命令分隔符DELIMITER

MySQL默认是以分号作为两个命令的分割点的。但有些命令块中包含分号,比如存储过程或触发器的定义中。为了使MySQL不把命令块中的分号误认做命令的分割点,需要在执行这种命令块前临时改一下命令分隔符。尤其注意,SQLYog里面写存储过程的时候,必须自行定义命令分隔符。

原文链接:https://blog.csdn.net/dyzhen/article/details/6681438

案例一:DEFINER

    CREATE DEFINER = 'admin'@'localhost' PROCEDURE account_count()

    BEGIN
        SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;
    END;

    在这个案例中,不论哪个用户A调用存储过程,
    存储过程都会以'admin'@'localhost'的权限去执行,
    即使这个用户A没有查询mysql.user表的权限。

案例二:INVOKER

    CREATE DEFINER = 'admin'@'localhost' PROCEDURE account_count()
        SQL SECURITY INVOKER
    BEGIN
        SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;
    END;

    在这个案例中,虽然存储过程语句中仍然带有DEFINER参数,
    但是由于SQL SECURITY指定了INVOKER,所以在存储过程执行的时候,
    会以调用者的额身份去执行。此时这个存储过程是否能成功执行,
    取决于调用者是否有mysql.user表的查询权限。


如果想所有地方都可以使用那么:
CREATE DEFINER=`root`@`%` PROCEDURE account_count()
BEGIN
   SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;
END;
 存储过程都会以'root'@'%'的权限去执行,
 'root'@'%'的意思是,密码正确的前提下任何人都可以使用MYSQL名为'root'用户的权限


也可以是:
CREATE DEFINER=CURRENT_USER PROCEDURE account_count() 
BEGIN
   SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;
END;
存储过程以当前登录用户的权限执行该存储过程

 

存储过程的三种参数

(1)IN型参数:它是默认模式。在存储过程中定义IN参数时,调用程序必须将参数传递给存储过程。 另外,IN参数的值被保护。这意味着即使在存储过程中更改了IN参数的值,在存储过程结束后仍保留其原始值。换句话说,存储过程只使用IN参数的副本。

 

(2)OUT型参数:可以在存储过程中更改OUT参数的值,并将其更改后的新值传递回调用程序。

 

(3)INOUT型参数: INOUT参数是IN和OUT参数的组合。这意味着调用程序可以传递参数,且存储过程可以修改INOUT参数并将更改后的新值传递回调用程序。

 

例如:CREATE DEFINER=`root`@`%` PROCEDURE `名称`(IN `param1` bigint,OUT `param2` bigint,INOUT `param3` varchar)

 

定义参数的方法:先声明时什么型的参数,参数名称,参数的数据类型 (IN `param` varchar);

 

mysql存储过程定义变量

1.declare
declare 变量名 变量类型  default  默认值;
declare a int DEFAULT 2;
declare定义的变量 相当于一个局部变量,  
在end之后失效,而且declare只能在begin,end中定义。

2.set
set @变量名=值
此处的变量不需要声明,mysql会自动根据值类型来确定类型,
这种变量要在变量名称前面加上“@”符号,叫做会话变量,
代表整个会话过程他都是有作用的,这个有点类似于全局变量一样。


3.select
同set

 

MySQL存储过程的控制语句

(1). 变量作用域:内部的变量在其作用域范围内享有更高的优先权,当执行到end 变量时,内部变量消失,此时已经在其作用域外,变量不再可见了,应为在存储过程外再也不能找到这个申明的变量,但是你可以通过out参数或者将其值指派给会话变量来保存其值。

(2)可以利用if或者case语句控制存储过程中的执行流程。

CREATE DEFINER=`root`@`%` PROCEDURE account_count(IN age int,OUT descrise varchar) BEGIN if (age >18) then set descrise = '成年人'; elseif (age >60) then sset descrise = '老年人'; else set descrise = '未知群体'; end if; select descrise as user_descrise ; END;
CREATE DEFINER=`root`@`%` PROCEDURE account_count(IN age int,OUT descrise varchar) BEGIN cast (age >18) then set descrise = '成年人'; when(age >60) then sset descrise = '老年人'; else set descrise = '未知群体'; end cast; select descrise as user_descrise ; END;

(3)可以利用loop或者while或者repeat来循环

CREATE DEFINER=CURRENT_USER PROCEDURE account_count() 
begin 
    declare counter int default 0;
         test_loop:loop 
            if counter < 10 then set counter = counter + 1; 
            else 
                leave test_loop;
             end if; 
        end loop test_loop; 
    select counter; 
end

 

CREATE DEFINER=CURRENT_USER PROCEDURE account_count() 
begin
    declare counter int default 0;
    while counter < 10 do
        set counter = counter + 1;
    end while;
    select counter;
end


 

CREATE DEFINER=CURRENT_USER PROCEDURE account_count() 
begin
    declare counter int default 0;
    repeat
        set counter = counter + 1;
    until counter > 10
    end repeat;
    select counter;
end

MySQL存储过程的基本函数

参考:http://blog.sina.com.cn/s/blog_86fe5b440100wdyt.html

(1).字符串类

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

TRIM([[BOTH|LEADING|TRAILING][padding] FROM]string2) //去除指定位置的指定字符

UCASE (string2 ) //转换成大写

RIGHT(string2,length) //取string2最后length个字符

SPACE(count) //生成count个空格

(2).数学类

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为小数位数]

(3).日期时间类

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) //小时

LAST_DAY(date) //date的月的最后日期

MICROSECOND(datetime) //微秒

MONTH(datetime) //月

MINUTE(datetime) //分返回符号,正负或0

SQRT(number2) //开平方

 

MySQL中的游标

1.声明游标

DECLARE cursor_name CURSOR FOR select org_id,user_code from user_inf;      // 相当于所有数据在游标中

2.打开游标

OPEN cursor_name

3.使用游标       

 FETCH cursor_name INTO org_id,user_code;       // 将游标数据取出来用

4.关闭游标

CLOSE cursor_name

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值