理解MYSQL存储过程

在MySQL 5中,终于引入了存储过程这一新特性,这将大大增强MYSQL的数据库处理能力。在本文中将指导读者快速掌握MySQL 5的存储过程的基本知识,带领用户入门。

  存储过程介绍

  存储过程是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中。用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程可由应用程序通过一个调用来执行,而且允许用户声明变量 。同时,存储过程可以接收和输出参数、返回执行存储过程的状态值,也可以嵌套调用。

  存储过程的优点

  作为存储过程,有以下这些优点:

  (1) 减少网络通信量。调用一个行数不多的存储过程与直接调用SQL语句的网络通信量可能不会有很大的差别,可是如果存储过程包含上百行SQL语句,那么其性能绝对比一条一条的调用SQL语句要高得多。

  (2) 执行速度更快。存储过程创建的时候,数据库已经对其进行了一次解析和优化。其次,存储过程一旦执行,在内存中就会保留一份这个存储过程,这样下次再执行同样的存储过程时,可以从内存中直接中读取。

  (3) 更强的安全性。存储过程是通过向用户授予权限(而不是基于表),它们可以提供对特定数据的访问,提高代码安全,比如防止 SQL注入。

  (4) 业务逻辑可以封装存储过程中,这样不仅容易维护,而且执行效率也高

  当然存储过程也有一些缺点,比如:

  (1) 可移植性方面:当从一种数据库迁移到另外一种数据库时,不少的存储过程的编写要进行部分修改。

  (2) 存储过程需要花费一定的学习时间去学习,比如学习其语法等。

  在MySQL中,推荐使用MySQL Query Browswer(http://dev.mysql.com/doc/query-browser/en/)这个工具去进行存储过程的开发和管理。下面分步骤来学习MYSQL中的存储过程。

  1、定义存储过程的结束符

  在存储过程中,通常要输入很多SQL语句,而SQL语句中每个语句以分号来结束,因此要告诉存储过程,什么位置是意味着整个存储过程结束,所以我们在编写存储过程前,先定义分隔符,我们这里定义//为分隔符,我们使用DELIMITER //这样的语法,就可以定义结束符了,当然你可以自己定义其他喜欢的符号。

  2、如何创建存储过程

  下面先看下一个简单的例子,代码如下:

DELIMITER //
CREATEPROCEDURE `p2` ()
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
COMMENT 'A procedure'
BEGIN
SELECT'Hello World !';
END//

  下面讲解下存储过程的组成部分:

    MySQL存储过程的创建

 

(1). 格式

MySQL存储过程创建的格式:CREATE PROCEDURE 过程名 ([过程参数[,...]])
[
特性 ...]过程体

这里先举个例子:
   

  1. mysql> DELIMITER // 
  2. mysql> CREATE PROCEDURE proc1(OUT int) 
  3.     -> BEGIN 
  4.     -> SELECT COUNT(*) INTO FROM user; 
  5.     -> END 
  6.     -> // 
  7. mysql> DELIMITER 
 
注:

1)这里需要注意的是DELIMITER //DELIMITER ;两句,DELIMITER是分割符的意思,因为MySQL默认以";"为分隔符,如果我们没有声明分割符,那么编译器会把存储过程当成SQL语句进行处理,则存储过程的编译过程会报错,所以要事先用DELIMITER关键字申明当前段分隔符,这样MySQL才会将";"当做存储过程中的代码,不会执行这些代码,用完了之后要把分隔符还原。

2)存储过程根据需要可能会有输入、输出、输入输出参数,这里有一个输出参数s,类型是int型,如果有多个参数用","分割开。



  1) 首先在定义好终结符后,使用CREATE PROCEDURE+存储过程名的方法创建存储过程,LANGUAGE选项指定了使用的语言,这里默认是使用SQL。

  2) DETERMINISTIC关键词的作用是,当确定每次的存储过程的输入和输出都是相同的内容时,可以使用该关键词,否则默认为NOT DETERMINISTIC。

  3) SQL SECURITY关键词,是表示调用时检查用户的权限。当值为INVOKER时,表示是用户调用该存储过程时检查,默认为DEFINER,即创建存储过程时检查。

  4) COMMENT部分是存储过程的注释说明部分。

  5) 在BEGIN END部分中,是存储过程的主体部分。



   变量

   Ⅰ. 变量定义

    DECLARE variable_name[,variable_name...] datatype [DEFAULT value];其中,datatypeMySQL的数据类型,如:int, float, date,varchar(length)

例如:

  1. DECLARE l_int int unsigned default 4000000; 
  2. DECLARE l_numeric number(8,2) DEFAULT 9.95; 
  3. DECLARE l_date date DEFAULT '1999-12-31'; 
  4. DECLARE l_datetime datetime DEFAULT '1999-12-31 23:59:59'; 
  5. DECLARE l_varchar varchar(255) DEFAULT 'This will not be padded';  

 

 

  Ⅱ. 变量赋值

        SET 变量名 = 表达式值 [,variable_name = expression...]

    用户变量

 

    ⅰ. MySQL客户端使用用户变量

  1. mysql SELECT 'Hello World' into @x; 
  2. mysql SELECT @x; 
  3. +-------------+ 
  4.   @x        
  5. +-------------+ 
  6. Hello World 
  7. +-------------+ 
  8. mysql SET @y='Goodbye Cruel World'; 
  9. mysql SELECT @y; 
  10. +---------------------+ 
  11.     @y              
  12. +---------------------+ 
  13. Goodbye Cruel World 
  14. +---------------------+ 
  15.  
  16. mysql SET @z=1+2+3; 
  17. mysql SELECT @z; 
  18. +------+ 
  19. @z   
  20. +------+ 
  21.    
  22. +------+ 

ⅱ. 在存储过程中使用用户变量

  1. mysql CREATE PROCEDURE GreetWorld( SELECT CONCAT(@greeting,' World'); 
  2. mysql SET @greeting='Hello'; 
  3. mysql CALL GreetWorld( ); 
  4. +----------------------------+ 
  5. CONCAT(@greeting,' World') 
  6. +----------------------------+ 
  7.  Hello World               
  8. +----------------------------+ 

 

. 在存储过程间传递全局范围的用户变量
  1. mysql> CREATE PROCEDURE p1()   SET @last_procedure='p1'; 
  2. mysql> CREATE PROCEDURE p2() SELECT CONCAT('Last procedure was ',@last_proc); 
  3. mysql> CALL p1( ); 
  4. mysql> CALL p2( ); 
  5. +-----------------------------------------------+ 
  6. CONCAT('Last procedure was ',@last_proc |  
  7. +-----------------------------------------------+ 
  8. Last procedure was p1                         
  9. +-----------------------------------------------+ 

 

 

注意:

用户变量名一般以@开头

滥用用户变量会导致程序难以理解及管理

 

(5). 注释

 

MySQL存储过程可使用两种风格的注释

双模杠:--

该风格一般用于单行注释

c风格: 一般用于多行注释


 


  3、调用存储过程的方法

  调用存储过程的方法很简单,只需要使用call命令即可,后面跟要调用存储过程的名称及输入的变量列表,比如:

CALL stored_procedure_name (param1, param2, ....)
CALL procedure1(10 , 'string parameter' , @parameter_var);

  4、修改和删除存储过程

  可以用ALTER的语法去修改存储过程的主要特征和参数,要修改其存储过程的主体部分的话,必须要先删除然后再重建。比如下面修改存储过程num_from_employee的定义。将读写权限改为MODIFIES SQL DATA,并指明调用者可以执行。代码执行如下:

ALTER PROCEDURE num_from_employee
MODIFIES SQL DATA SQL SECURITY INVOKER ;

  而删除存储过程的语法为使用DROP关键词即可。如下

DROP PROCEDURE IF EXISTS p2;

MySQL存储过程的查询

我们像知道一个数据库下面有那些表,我们一般采用showtables;进行查看。那么我们要查看某个数据库下面的存储过程,是否也可以采用呢?答案是,我们可以查看某个数据库下面的存储过程,但是是令一钟方式。

我们可以用

select namefrom mysql.proc where db=’数据库名’;

或者

selectroutine_name from information_schema.routines whereroutine_schema='数据库名';

或者

show procedurestatus where db='数据库';

进行查询。

如果我们想知道,某个存储过程的详细,那我们又该怎么做呢?是不是也可以像操作表一样用describe表名进行查看呢?

答案是:我们可以查看存储过程的详细,但是需要用另一种方法:

SHOW CREATEPROCEDURE 数据库.存储过程名;

就可以查看当前存储过程的详细。

  MySQL存储过程的基本函数

 

(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 ]) //strposition开始,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) //小时 LAST_DAY(date) //date的月的最后日期 MICROSECOND(datetime) //微秒 MONTH(datetime) // MINUTE(datetime) //返回符号,正负或0 SQRT(number2) //开平方
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值