mysql存储过程和函数


1.创建存储过程和函数... 2

1.1 创建存储过程... 2

1.2 创建存储函数... 3

2.变量的使用... 4

2.1 定义变量... 4

2.2 为变量赋值... 4

3.定义条件和处理程序... 4

3.1 定义条件... 5

3.2 定义处理程序... 5

4.光标的使用... 6

4.1声明光标... 6

4.2打开光标... 6

4.3使用光标... 6

4.4 关闭光标... 7

5.流程控制的使用... 7

5.1 IF语句... 7

5.2 CASE语句... 7

5.3 LOOP语句... 8

5.4 LEAVE语句... 8

5.5 ITERATE语句... 8

5.6 REPEAT语句... 9

5.7 WHILE语句... 9

6.调用存储过程和函数... 9

6.1 调用存储过程... 10

6.2 调用存储函数... 10

7.查看存储过程和函数... 10

7.1 SHOW STATUS 语句查看那存储过程和函数的状态... 10

7.2 SHOW CREATE语句查看存储过程和函数的定义... 11

7.3 information_schema.Routines表中查看存储过程和函数的信息... 12

8.修改存储过程和函数... 12

9.删除存储过程及函数... 13

10.本次实例... 13

 

 

存储过程和函数式数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句。存储过程和函数可以避免开发人员编写相同的SQL语句,而且,存储过程和函数是在mysql服务器中存储和执行的,可以减少客户端和服务器的数据传输。

 

1.创建存储过程和函数

创建存储过程和函数式指将经常使用的一组SQL语句组合在一起,兵将这些SQL语句当做一个整体存储在mysql服务器中。

 

1.1 创建存储过程

语法:

Name:'CREATE PROCEDURE'

Description:

Syntax:

CREATE

    PROCEDURE sp_name ([proc_parameter[,...]])

[characteristic ...] routine_body

 

CREATE PROCEDURE表示创建存储过程的关键字

sp_name 表示存储过程的名字

([proc_parameter[,...]]) 表示存储过程的参数列表

[characteristic ...] 表示存储过程的特性

routine_body 表示SQL代码的内容

 

参数列表:

([proc_parameter[,...]]),由三部分组成,输入输出类型,参数名称,参数类型

[ IN |OUT | INOUT ] param_name type

 

存储过程特性:

characteristic:

    LANGUAGE SQL

  | [NOT] DETERMINISTIC

  | { CONTAINS SQL | NO SQL | READS SQL DATA |MODIFIES SQL DATA }

  | SQL SECURITY { DEFINER | INVOKER }

  | COMMENT 'string'

一些注释,谁有权执行后面的SQL语句等,都是特性指定的。

 

实例:

创建一个名为num_from_employee的存储过程.

DELIMITER &&

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

        READS SQL DATA

        BEGIN

               SELECT COUNT(*) INTO count_num

               FROM test.employee

               WHERE d_id=emp_id;

        END

        &&

DELIMITER ;

 

mysql> callnum_from_employee(1001,@count_num);

mysql> select @count_num;

1.2 创建存储函数

语法:

CREATE

    FUNCTION sp_name ([func_parameter[,...]])

    RETURNS type

    [characteristic ...] routine_body

 

CREATE FUNCTION 表示创建存储函数的关键字

RETURNS type 表示返回值的类型,存储过程没有这个。

([func_parameter[,...]]) 表示参数类型,不需要指定输入输出,这里与存储过程的不同。

 

实例:

下面创建一个名为name_from_employee的存储函数

DELIMITER &&

CREATE FUNCTIONname_from_employee(emp_id INT)

        RETURNS VARCHAR(20)

        READS SQL DATA

        BEGIN

              RETURN (SELECT name

              FROM employee

              WHERE num=emp_id);

        END

        &&

DELIMITER ;

 

mysql> selectname_from_employee(1);

 

 

2.变量的使用

存储过程和函数中可以定义和使用变量。用户可以使用DECLARE关键字来定义变量。然后可以为变量赋值,这些变量的作用范围是BEGIN...END程序段中。

2.1 定义变量

定义变量mysql_sql,数据类型为INT型,默认值为10

DECLARE my_sql INT DEFAULT 10;

2.2 为变量赋值

方法一:为变量my_sql赋值为30

SET my_sql=30;

方法二:employee表中查询id2的记录,将该记录的d_id值赋给变量my_sql

SELECT d_id INTO my_sql FROM employeeWHERE id=2;

 

 

3.定义条件和处理程序

定义条件和处理程序是事先定义程序执行过程中可能遇到的问题。并且可以再处理程序中定义解决这些问题的办法。这种方法可以提前预测可能出现的问题,兵提出解决办法。这样可以增强程序处理问题的能力,避免程序异常停止。Mysql中都是通过DECLARE关键字来定义条件和处理程序的。

3.1 定义条件

语法:

DECLAREcondition_name CONDITION FOR condition_value

condition_value:

SQLSTATE[VALUE] sqlstate_value | mysql_error_code

 

实例:

下面定义“ERROR 1146(42S02)”中这个错误,名称为can_not_find,可以用两种不同的方法定义

方法一:使用sqlstate_value

DECLARE can_not_find CONDITION FORSQLSTATE '42S02';

方法二:使用mysql_error_code

DECLARE can_not_find CONDITION FOR 1146;

 

3.2 定义处理程序

Name:'DECLARE HANDLER'

Description:

Syntax:

DECLAREhandler_type HANDLER

    FOR condition_value [, condition_value] ...

    statement

 

handler_type:

  CONTINUE

  | EXIT

  | UNDO

 

condition_value:

  SQLSTATE [VALUE] sqlstate_value

  | condition_name

  | SQLWARNING

  | NOT FOUND

  | SQLEXCEPTION

  | mysql_error_code

实例:

下面是定义处理程序的几种方式

方法一:捕获sqlstate_value

DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info='CAN NOT FIND';

方法二:捕获mysql_error_code

DECLARE CONTINUE HANDLER FOR 1146 SET@info='CAN NOT FIND';

方法三:先定义条件,然后调用

DECLARE can_not_find CONDITION FOR 1146;

DECLARE CONTINUE HANDLER FOR can_not_find SET @info='CAN NOT FIND';

方法四:使用SQLWARNING

DECLARE EXIT HANDLER FOR SQLWARNING SET @info='ERROR';

方法五:使用NOT FOUND

DECLARE EXIT HANDLER NOT FOUND SET @info='CAN NOT FIND';

方法六:使用SQLEXCEPTION

DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info='ERROR';

 

 

4.光标的使用

查询语句可能查出多条记录,在存储过程和存储函数中使用光标逐条读取查询结果集中的记录。有些书上将光标称为游标。光标的使用包括声明光标、打开光标、使用光标和关闭光标。光标必须声明在处理程序之前,并且声明在变量和条件之后。

4.1声明光标

下面声明一个名为cur_employee的光标

DECLARE cur_employee CURSOR FOR SELECT name,age FROM employee;

4.2打开光标

下面打开一个名为cur_employee的光标

OPEN cur_employee;

4.3使用光标

下面使用一个名为cur_employee的光标,将查询出来的数据存入emp_nameemp_age这两个变量中

FETCH cur_employee INTO emp_name,emp_age;

4.4 关闭光标

下面关闭一个名为cur_employee的光标

CLOSE cur_employee;

 

 

5.流程控制的使用

存储过程和存储函数中可以使用流程控制来控制语句的执行。Mysql中可以使用IF语句、CASE语句、LOOP语句、LEAVE语句、ITERATE语句、REPEAT语句、WHILE语句来进行流程控制。

5.1 IF语句

语法:

IFsearch_condition THEN statement_list

  {ELSEIF search_condition THENstatement_list}....

  {ELSE statement_list}

END IF

示例:

IF age > 20 THEN SET @count1=@count1+1;

  ELSEIF age=20 THEN@count2=@count2+1;

  ELSE @count3=@count3+1;

END IF;

 

5.2CASE语句

语法一:

CASEcase_value

  WHEN when_value THEN statement_list;

  {WHEN when_value THEN statement_list}...

  {ELSE statement_list}

END CASE

 

语法二:

CASE

  WHEN search_condition THEN staterment_list

  {WHEN search_condition THENstatement_list}....

  {ELSE statement_list}

END CASE

示例:

CASE age

  WHEN 20 THEN SET@count1=@count1+1;

  ELSE SET @count2=@count2+1;

END CASE;

 

5.3LOOP语句

语法:

[begin_label:]LOOP

    statement_list

END LOOP[end_label]

示例:

add_num:LOOP

  SET @count=@count+1;

END LOOP add_num;

 

5.4LEAVE语句

示例:

add_num:LOOP

  SET @count=@count+1;

  IF @count=100 THEN

    LEAVE add_num

END LOOP add_num;

 

5.5ITERATE语句

add_num:LOOP

  SET @count=@count+1;

  IF @count=100 THEN

LEAVE add_num

  ELSE IF MOD(@count,3)=0 THEN

ITERATE add_num;

  SELECT * FROM employee;

END LOOP add_num;

 

5.6REPEAT语句

语法:

[begin_label:]REPEAT

  statement_list

  UNTIL search_condition

ENDREPEAT [end_label]

 

示例:

REPEAT

  SET @count=@count+1;

  UNTIL @count=100

END REPEAT;

 

5.7WHILE语句

语法:

[begin_label:] WHILE search_condition DO

   statement_list

END WHILE [end_label]

示例:

WHILE @count<100 DO

  SET @count=@count+1;

END WHILE;

 

 

6.调用存储过程和函数

存储过程和存储函数都是存储在服务器端的SQL语句的集合。要使用这些已经定义好的存储过程和存储函数就必须要通过调用的方式来实现。存储过程是通过CALL语句来调用的。而存储函数的使用方法与mysql内部函数的使用方法是一样的。执行存储过程和存储环视需要拥有EXECUTE权限。EXECUTE权限的信息存储在information_schema数据库下面的USER_PRIVILEGES表中。

6.1 调用存储过程

语法:

CALL sp_name([parameter[,…..]]);

见创建存储过程实例

6.2 调用存储函数

见创建存储函数实例

 

 

7.查看存储过程和函数

存储过程和函数创建以后,用户可以查看存储过程和函数的状态和定义。用户可以通过SHOW STATUS语句来查看存储过程和函数的状态,也可以通过SHOW CREATE语句来查看存储过程和函数的定义。用户也可以通过查询information_schema数据库下的Routines表来查看存储过程和函数的信息。

 

7.1SHOW STATUS 语句查看那存储过程和函数的状态

语法:

SHOW {PROCEDURE|FUNCTION} STATUS [LIKE 'pattern'];

 

查看存储过程:

mysql> showprocedure status\G

*************************** 1. row ***************************

                  Db: navi_db

                Name:UP_RPT_CLIENT_LOGIN

                Type: PROCEDURE

             Definer:pgm@localhost

            Modified: 2014-06-06 12:26:48

             Created: 2014-06-0612:26:48

       Security_type: DEFINER

             Comment:

character_set_client: utf8

collation_connection: utf8_general_ci

  Database Collation:utf8_general_ci

 

查看存储函数:

mysql> showfunction status\G

*************************** 1. row ***************************

                  Db: test

                Name:name_from_employee

                Type: FUNCTION

             Definer:root@localhost

            Modified: 2014-09-1014:17:22

             Created: 2014-09-1014:17:22

       Security_type: DEFINER

             Comment:

character_set_client: utf8

collation_connection: utf8_general_ci

  Database Collation:utf8_general_ci

 

7.2SHOW CREATE语句查看存储过程和函数的定义

语法:

SHOW CREATE {PROCEDURE|FUNCTION} sp_name;

 

查看存储过程定义:

mysql> showcreate procedure num_from_employee\G

*************************** 1. row ***************************

           Procedure:num_from_employee

            sql_mode:

    Create Procedure: CREATEDEFINER=`root`@`localhost` PROCEDURE `num_from_employee`(IN emp_id INT,OUTcount_num INT)

    READS SQL DATA

BEGIN

               SELECT COUNT(*)INTO count_num

               FROM test.employee

               WHERE d_id=emp_id;

        END

character_set_client: utf8

collation_connection: utf8_general_ci

  Database Collation:utf8_general_ci

 

查看存储函数定义:

mysql> showcreate function name_from_employee\G

*************************** 1. row ***************************

            Function:name_from_employee

            sql_mode:

     Create Function: CREATEDEFINER=`root`@`localhost` FUNCTION `name_from_employee`(emp_id INT) RETURNSvarchar(20) CHARSET utf8

    READS SQL DATA

BEGIN

              RETURN (SELECT name

              FROM employee

              WHERE num=emp_id);

        END

character_set_client: utf8

collation_connection: utf8_general_ci

  Database Collation:utf8_general_ci

 

7.3 information_schema.Routines表中查看存储过程和函数的信息

语法:

SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME='sp_name';

 

 

8.修改存储过程和函数

修改存储过程和函数是指修改已经定义好的存储过程和函数。mysql中通过ALTER PROCEDURE语句来修改存储过程。通过ALTER FUNCTION语句来修改存储函数。

 

语法:

ALTER {PROCEDURE|FUNCTION} sp_name [characteristic…]

Characteristic:

{CONTAINS SQL|NO SQL|READS SQL DATA|MODIFIES SQL DATA}

|SQL SECURITY {DEFINER|INVOKER}

|COMMENT 'string'

 

示例修改存储过程:(修改存储函数略)

修改存储过程num_from_employee的定义,将读写权限改为MODIFIES SQL DATA,指明调用者可执行,并添加注释hi feinno.

ALTER PROCEDURE num_from_employee

MODIFIES SQL DATA

SQL SECURITY INVOKER

COMMENT 'hi feinno';

 

myql>select specific_name,sql_data_access,security_type,routine_commitfrom information_schema.routines where routine_name='num_from_employee';

 

 

9.删除存储过程及函数

语法:

DROP {PROCEDURE|FUNCTION} sp_name;

 

示例删除存储过程及函数

DROP PROCEUDRE test.num_from_employee;

DROP FUNCTION test.name_from_employee;

 

select count(*) from information_schema.routineswhere routine_name='num_from_employee';

select count(*) frominformation_schema.routines where routine_name='name_from_employee';

 

 

10.本次实例

food表上创建名为food_price_count的存储过程,存储过程food_price_count有三个参数。输入参数为price_info1price_info2,输出count。存储过程的作用是查询food表中食品单价高于price_info1且低于price_info2的食品种数,然后由count参数输出。并且计算满足条件的单价的总和。

 

CREATE table food(

id INT(10) PRIMARY KEYNOT NULL,

name VARCHAR(20) NOTNULL,

company VARCHAR(20) NOTNULL,

price DOUBLE NOT NULL,

produce_time YEAR NOTNULL,

valiadity_time INT NOTNULL,

address VARCHAR(50)DEFAULT NULL

);

 

INSERT INTO foodVALUES(1,'光磊饼干','光磊饼干厂',2.5,'2008',3,'北京'),

(2,'宪政牛奶','宪政牛奶厂',3.5,'2009',3,'秦皇岛'),

(3,'兴周果冻','兴周果冻厂',1.5,'2007',2,'保定'),

(4,'GG咖啡','GG咖啡厂',20,'2002',5,'天津'),

(5,'XX奶糖','XX奶糖厂',14,'2003',3,'上海');

 

DELIMITER &&

CREATE PROCEDURE food_price_count(IN price_info1 FLOAT,IN price_info2FLOAT,OUT count INT)

READS SQL DATA

BEGIN

  DECLARE temp FLOAT;

  DECLARE match_price CURSOR FORSELECT price FROM food;

  DECLARE EXIT HANDLER FOR NOTFOUND CLOSE match_price;

  SET @sum=0;

  SELECT COUNT(*) INTO count FROMfood

WHERE price BETWEEN price_info1 AND price_info2;

  OPEN match_price;

  REPEAT

FETCH match_price INTO temp;

  IF temp>price_info1 ANDtemp<price_info2

    THEN SET @sum=@sum+temp;

  END IF;

  UNTIL 0 END REPEAT;

  CLOSE match_price;

END &&

DELIMITER ;

mysql> call food_price_count(2,18,@count);

mysql> select @count,@sum; 

 

解释:

CREATE PROCEDURE food_price_count(IN price_info1 FLOAT,IN price_info2FLOAT,OUT count INT)  创建存储过程。。。

READS SQL DATA 设置为只读数据

BEGIN 语句开始

DECLARE temp FLOAT 定义一个temp变量

DECLARE match_price CURSOR FOR SELECT price FROM food 定义光标,从food表中查询出价格

DECLARE EXIT HANDLER FOR NOT FOUND CLOSE match_price 定义遇到光标关闭的话就结束执行

SET @sum=0 设置一个sum求和,初始值为0

SELECT COUNT(*) INTO count FROM food

WHERE price BETWEEN price_info1 AND price_info2  将查询出来的count(*)赋值给count

OPEN match_price 打开光标

REPEAT 使用repeat循环

FETCH match_price INTO temp 读取光标里面的内容将其放到temp

IF temp>price_info1 AND temp<price_info2 如果temp中的值大于price_info1字段中的值且小于price_info2中的值

THEN SET @sum=@sum+temp  则将sum求和

END IF 结束IF语句

UNTIL 0 END REPEAT 直到光标等于0时,结束repeat循环

CLOSE match_price 关闭光标

END 语句结束


你可能感兴趣的:(mysql,存储)