MySQL存储过程名词解释_MySQL存储过程详解

一、使用场景

1.执行时简单:名字+参数

2.存储过程中可以有一个、多个sql语句。

问:为啥要用存储过程?

答:

①将重复性很高的一些操作,封装到一个存储过程中。简化了对这些SQL的调用。

②批量处理sql+循环

③统一接口

注意:mysql中,存储功能相对较弱。使用较少。

二、基本建立语法

例1:

DELIMITER $$

CREATE PROCEDURE delete_matches(IN p playerno INTEGER)

BEGIN

DELETE FROM MATCHES

WHERE playerno=p_playerno;

END$$

DELIMITER;

call delete_matches(6);

例2:

delimiter $$

CREATE PROCEDURE dorepeat(p1 INT)

BEGIN

SET @x = 0; --》用set赋值, repeat循环

REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;

END$$

delimiter ;

CALL dorepeat(1000);

SELECT @x;

执行后:@x的值为1001

@变量名字的作用:

①存储过程中定义,存储过程中进行处理,加减乘除。

②存储过程外面可以访问这个@变量,这个变量保存了存储过程中对这个变量处理后的值。

@x:用户变量

存储过程外面可以访问,一直被保存。

直接使用set @x=0;就可以生成这么一个变量,不需要数据类型。

三、存储过程参数

三类:in(输入参数)、out(输出参数)、inout(输入和输出参数)

存储过程需要是活的–》输入不同的参数,执行不同的操作,处理不同的行等等。

IN参数

DELIMITER $$

CREATE PROCEDURE delete matches(IN p playerno INTEGER)

BEGIN

DELETE FROM MATCHES

WHERE playerno=p_playerno;

END$$

DELIMITER;

call delete_matches(6);

IN参数可以是:数值100、赋值了的变量 set @a=100;

OUT参数

delimiter $$

CREATE PROCEDURE simpleproc (OUT param1 INT)

BEGIN

SELECT COUNT(*) INTO param1 FROM PLAYERS;

END$$

delimiter ;

CALL simpleproc(@a);

SELECT @a;

OUT参数:变量就可以,可以没有赋值。 @a

INOUT参数

delimiter $$

CREATE PROCEDURE simpleproc1(INOUT param1 INT)

BEGIN

SELECT COUNT(*) INTO param1 FROM PLAYERS where PLAYERNO<=param1;

END$$

delimiter ;

set @a=10;

CALL simpleproc1(@a); --》调用存储过程时,只要引用变量就行!

SELECT @a;

INOUT参数:只能是赋了值得变量。 set @a=100;

一个存储过程如果想有返回值:

1.out参数

2.inout参数

3.在存储过程内部定义用户变量

@变量名字

建议:返回值使用out参数;输入值使用in参数。

四、begin…end语法

为什么需要begin…end?

答:

①因为begin…end语句之间的n条语句属于一条语句,一个整体。

②成对出现。

BEGIN

sql语句

END$$

五、变量

1.用户变量@

随处可定义,随处可使用;

不定义可直接使用;

随处可见;

内部定义,外部可见。

2.局部变量,只有名字,没有@符号

先定义,再使用;

只在存储过程内部可见;只能定义在begin后面!

注意:在存储过程内部,使用局部变量,不要使用用户变量。

用户变量和局部变量的区别:

①局部变量前面没有@符号

②当begin…end块处理完后,局部变量就消失了,而用户变量存在于整个会话之中。

定义局部变量:

DECLARE 变量名字 类型 [default] –》而且declare必须紧接着begin!

例:

DECLARE var_name [, var_name] ... type [DEFAULT value]

delimiter $$

CREATE PROCEDURE sp1 (x VARCHAR(10))

BEGIN

DECLARE newname VARCHAR(10);

DECLARE xid INT;

SELECT xname, id INTO newname, xid

FROM table1 WHERE xname = x;

SELECT newname;

END$$

delimiter ;

call sp1('a');

初始化局部变量:

delimiter $$

CREATE PROCEDURE test1(OUT num1 INTEGER)

BEGIN

DECLARE num2 INTEGER DEFAULT (SELECT count(*) FROM PLAYERS);

SET num1 = num2;

END$$

delimiter ;

begin…end的作用域:

外层看不到内层;

内层可以看到外层;

平行互相看不见。

SET

可以给用户变量和局部变量赋值

用户变量内外都可以使用

局部变量,只有begin end之间可以使用,而且需要declare定义

六、IF…ELSE

DELIMITER $$ --》定义$$为分界符

CREATE PROCEDURE difference(

IN p1 INTEGER, --》整数

IN p2 INTEGER,

OUT p3 INTEGER)

BEGIN

IF p1 > p2 THEN

SET p3 = 1;

ELSEIF p1= p2 THEN

SET p3 = 2;

ELSE

SET p3 = 3;

END IF;

END$$

DELIMITER ;

mysql> call difference(1,10,@p);

Query OK, 0 rows affected (0.00 sec)

mysql> select @p;

+------+

| @p |

+------+

| 3 |

+------+

1 row in set (0.01 sec)

七、函数

1.返回值

两个return:一个标志返回什么类型;一个实际的返回值。

2.调用函数:函数需要出现在=的右边

例子:

DELIMITER $$

CREATE FUNCTION SimpleCompare(n INT, m INT)

RETURNS VARCHAR(20)

BEGIN

DECLARE s VARCHAR(20);

IF n > m THEN SET s = '>';

ELSEIF n = m THEN SET s = '=';

ELSE SET s = '

END IF;

SET s = CONCAT(n, ' ', s, ' ', m);

RETURN s;

END$$

DELIMITER ;

mysql> select SimpleCompare(1,2) ;

+--------------------+

| SimpleCompare(1,2) |

+--------------------+

| 1 < 2 |

+--------------------+

1 row in set (0.01 sec)

mysql> set @a=SimpleCompare(1,2) ;

Query OK, 0 rows affected (0.01 sec)

mysql> select @a;

+-------+

| @a |

+-------+

| 1 < 2 |

+-------+

1 row in set (0.00 sec)

八、case…end case

例1:

DELIMITER $$

CREATE PROCEDURE difference1(

IN p1 INTEGER,

IN p2 INTEGER,

OUT p3 INTEGER)

BEGIN

CASE

WHEN p1 > p2 THEN

SET p3 = 1;

WHEN p1= p2 THEN

SET p3 = 2;

ELSE

SET p3 = 3;

END CASE;

END$$

DELIMITER ;

mysql> call difference1(1,100,@a);

Query OK, 0 rows affected (0.01 sec)

mysql> select @a;

+------+

| @a |

+------+

| 3 |

+------+

1 row in set (0.00 sec)

例2:

DELIMITER $$

CREATE PROCEDURE p(x INT)

BEGIN

DECLARE v INT DEFAULT 1;

set v=x;

CASE v

WHEN 2 THEN SELECT v;

WHEN 3 THEN SELECT 0;

ELSE

BEGIN

END;

END CASE;

END$$

DELIMITER ;

mysql> call p(2);

+------+

| v |

+------+

| 2 |

+------+

1 row in set (0.00 sec)

Query OK, 0 rows affected (0.01 sec)

mysql> call p(3);

+---+

| 0 |

+---+

| 0 |

+---+

1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

九、while

例题:

DELIMITER $$

CREATE PROCEDURE dowhile(x int)

BEGIN

DECLARE v1 INT DEFAULT 5;

set v1=x;

WHILE v1 > 0 DO

select v1;

SET v1 = v1 - 1;

END WHILE;

END$$

DELIMITER ;

mysql> call dowhile(10);

+------+

| v1 |

+------+

| 10 |

+------+

1 row in set (0.01 sec)

+------+

| v1 |

+------+

| 9 |

+------+

1 row in set (0.01 sec)

。。。一直到1

十、repeat…until

先执行,再判断。

例题:

delimiter //

CREATE PROCEDURE dorepeat1(p1 INT)

BEGIN

SET @x = 0;

REPEAT

SET @x = @x + 1;

UNTIL @x > p1

END REPEAT;

END//

delimiter ;

mysql> call dorepeat1(10);

Query OK, 0 rows affected (0.01 sec)

mysql> select @x;

+------+

| @x |

+------+

| 11 |

+------+

十一、loop配合leave

leave:跳出语句块

DELIMITER $$

CREATE PROCEDURE small_exit(OUT p1 INTEGER,OUT p2 INTEGER)

BEGIN

SET p1 = 1;

SET p2 = 1;

block1: BEGIN

LEAVE block1; --》就不再执行下面那个p2=3了!!

SET p2 = 3;

END block1;

SET p1 = 4;

END$$

DELIMITER ;

mysql> call small_exit(@a,@b);

Query OK, 0 rows affected (0.00 sec)

mysql> select @a,@b;

+------+------+

| @a | @b |

+------+------+

| 4 | 1 |

+------+------+

1 row in set (0.00 sec)

loop

DELIMITER $$

CREATE PROCEDURE wait_n(IN wait_seconds INTEGER)

BEGIN ---》PS:interval 间隔

DECLARE end_time datetime DEFAULT now() + INTERVAL wait_seconds SECOND;

wait_loop:LOOP

IF now() > end_time THEN

LEAVE wait_loop;

END IF;

END LOOP wait_loop;

END$$

DELIMITER ;

mysql> call wait_n(10);

Query OK, 0 rows affected (10.55 sec)

while:先判断再执行

repeat…until:先执行再判断

loop:判断可以放在loop…end loop之间的任意位置

iterate:跳出本次循环

十二、ITERATE

DELIMITER $$

CREATE PROCEDURE doiterate3(p1 INT,p2 INT)

BEGIN

label1: LOOP

SET p1 = p1 + 1;

SET p2 = p2 + 1;

IF p1 < 10 THEN

select p1;

ITERATE label1; --》跳出本次label1循环!继续下次label1循环。

select p2; --》一直没执行

END IF;

LEAVE label1;

END LOOP label1;

SET @x = p1;

END$$

DELIMITER ;

mysql> call doiterate3(10,10); --》直接就执行leave label1

Query OK, 0 rows affected (0.01 sec)

mysql> call doiterate3(1,1); ---》显示p1=2,3,4...9

+------+

| p1 |

+------+

| 2 |

+------+

1 row in set (0.00 sec)

+------+

| p1 |

+------+

| 3 |

+------+

1 row in set (0.00 sec)

十三、select info经典用法

DELIMITER $$

CREATE PROCEDURE total_penalties_player(

IN p_playerno INTEGER,

OUT total_penalties DECIMAL(8,2))

BEGIN

SELECT sum(amount) ---》去掉into的select只能返回一行数据!

INTO total_penalties --》把select 的结果into给(多个)变量!!

FROM PENALTIES

WHERE playerno = p_playerno;

END$$

DELIMITER ;

mysql> call total_penalties_player(44,@a); ---》计算44号人的罚款总额,结果赋给@a

Query OK, 1 row affected (0.01 sec)

mysql> select @a;

+--------+

| @a |

+--------+

| 130.00 |

+--------+

1 row in set (0.00 sec)

小结:

1.经典的方式:将select返回的多列单行数据赋值给相应的变量(一个列对应一个变量)

2.这些变量经常是out参数

3.也就是变相的将select的结果传给了存储过程,让外面的程序可见。

例2:into给多个参数:

DELIMITER $$

CREATE PROCEDURE get_address(

IN p_playerno SMALLINT,

OUT p_street VARCHAR(30),

OUT p_houseno VARCHAR(4),

OUT p_town VARCHAR(30),

OUT p_postcode VARCHAR(6))

BEGIN

SELECT street, houseno, town, postcode

INTO p_street, p_houseno, p_town, p_postcode

FROM PLAYERS

WHERE playerno = p_playerno;

END$$

DELIMITER ;

mysql> call get_address(44,@a,@b,@c,@d);

Query OK, 1 row affected (0.01 sec)

mysql> select @a,@b,@c,@d;

+--------------+------+-----------+--------+

| @a | @b | @c | @d |

+--------------+------+-----------+--------+

| Lewis Street | 23 | Inglewood | 4444LJ |

+--------------+------+-----------+--------+

1 row in set (0.00 sec)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值