MySQL 5.0 新特点教程 存储历程:第三讲[MySQL防范]
本文“MySQL 5.0 新特点教程 存储历程:第三讲[MySQL防范]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
The New SQL Statements 新SQL语句
Variables 变量
在复合语句中声明变量的指令是DECLARE.
(1) Example with two DECLARE statements
两个DECLARE语句的例子
CREATE PROCEDURE p8 ()
BEGIN
DECLARE a INT;
DECLARE b INT;
SET a = 5;
SET b = 5;
INSERT INTO t VALUES (a);
SELECT s1 * a FROM t WHERE s1 >= b;
END; // /* I won't CALL this */
在历程中定义的变量并非真正的定义,你只是在BEGIN/END块内定义了罢了(译注:也就是形参).
注意这些变量和会话变量不一样,不能利用修饰符@你必须清楚的在BEGIN/END块中声明变量和它们的范例.
变量一旦声明,你就可以在任何能利用会话变量、文字、列名的地方利用.
(2)
Example with no DEFAULT clause and SET statement
没有默许子句和设定语句的例子
CREATE PROCEDURE p9 ()
BEGIN
DECLARE a INT /* there is no DEFAULT clause */;
DECLARE b INT /* there is no DEFAULT clause */;
SET a = 5; /* there is a SET statement */
SET b = 5; /* there is a SET statement */
INSERT INTO t VALUES (a);
SELECT s1 * a FROM t WHERE s1 >= b;
END; // /* I won't CALL this */
有很多初始化变量的办法.假如没有默许的子句,那么变量的初始值为NULL.你可以在任什么时刻候利用SET语句给变量赋值.
(3)
Example with DEFAULT clause
含有DEFAULT子句的例子
CREATE PROCEDURE p10 ()
BEGIN
DECLARE a, b INT DEFAULT 5;
INSERT INTO t VALUES (a);
SELECT s1 * a FROM t WHERE s1 >= b;
END; //
我们在这里做了一些改变,但是后果还是一样的.在这里利用了DEFAULT子句来设定初始值,这就不需求把DECLARE和SET语句的实现脱离了.
(4) Example of CALL
调用的例子
MySQL> CALL p10() //
+--------+
| s1 * a |
+--------+
| 25 |
| 25 |
+--------+
2 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
后果显示了历程能正常工作
(5) Scope
作用域
CREATE PROCEDURE p11 ()
BEGIN
DECLARE x1 CHAR(5) DEFAULT 'outer';
BEGIN
DECLARE x1 CHAR(5) DEFAULT 'inner';
SELECT x1;
END;
SELECT x1;
END; //
目前我们来谈论一下作用域的问题.例子中有嵌套的BEGIN/END块,当然这是合理的.同时包含两个变量,名字都是x1,这样也是合理的.内部的变量在其作用域内享有更高的优先权.当履行到END语句时,内部变量消逝,此时已经在其作用域外,变量不再可见了,因此在存储历程外再也不能找到这个声明了的变量,但是你可以通过OUT参数大概将其值指派 给会话变量来保存其值.
调用作用域例子的历程:
mysql> CALL p11()//
+-------+
| x1 |
+-------+
| inner |
+-------+
+-------+
| x1 |
+-------+
| outer |
+-------+
我们看到的后果时第一个SELECT语句检索到最内层的变量,第二个检索到第二层的变量
[1] [2] [3] [4] [5] [6] 下一页
Conditions and IF-THEN-ELSE 条件式和IF-THEN-ELSE
1.
目前我们可以写一些包含条件式的例子:
CREATE PROCEDURE p12 (IN parameter1 INT)
BEGIN
DECLARE variable1 INT;
SET variable1 = parameter1 + 1;
IF variable1 = 0 THEN
INSERT INTO t VALUES (17);
END IF;
IF parameter1 = 0 THEN
UPDATE t SET s1 = s1 + 1;
ELSE
UPDATE t SET s1 = s1 + 2;
END IF;
END; //
这里是一个包含IF语句的历程.里面有两个IF语句,一个是IF语句END IF,另一个是IF语句ELSE语句END IF.我们可以在这里利用复杂的历程,但我会尽大概使其简单让你能更简单弄清楚.
2.
CALL p12 (0) //
我们调用这个历程,传入值为0,这样parameter1的值将为0.
3.
CREATE PROCEDURE p12 (IN parameter1 INT)
BEGIN
DECLARE variable1 INT;
SET variable1 = parameter1 + 1; <--
IF variable1 = 0 THEN
INSERT INTO t VALUES (17);
END IF;
IF parameter1 = 0 THEN
UPDATE t SET s1 = s1 + 1;
ELSE
UPDATE t SET s1 = s1 + 2;
END IF;
END; //
这里变量variable1被赋值为parameter1加1的值,所以履行后变量variable1为1.
4.
CREATE PROCEDURE p12 (IN parameter1 INT)
BEGIN
DECLARE variable1 INT;
SET variable1 = parameter1 + 1;
IF variable1 = 0 THEN <--
INSERT INTO t VALUES (17);
END IF;
IF parameter1 = 0 THEN
UPDATE t SET s1 = s1 + 1;
ELSE
UPDATE t SET s1 = s1 + 2;
END IF;
END; //
因为变量variable1值为1,因此条件"if variable1 = 0"为假,
IF
……
END IF
被跳过,没有被履行.
5.
CREATE PROCEDURE p12 (IN parameter1 INT)
BEGIN
DECLARE variable1 INT;
SET variable1 = parameter1 + 1;
IF variable1 = 0 THEN
INSERT INTO t VALUES (17);
END IF;
IF parameter1 = 0 THEN <--
UPDATE t SET s1 = s1 + 1;
ELSE
UPDATE t SET s1 = s1 + 2;
END IF;
END; //
到第二个IF条件,判断后果为真,于是中间语句被履行了
6.
CREATE PROCEDURE p12 (IN parameter1 INT)
BEGIN
DECLARE variable1 INT;
SET variable1 = parameter1 + 1;
IF variable1 = 0 THEN
INSERT INTO t VALUES (17);
END IF;
IF parameter1 = 0 THEN
UPDATE t SET s1 = s1 + 1; <--
ELSE
UPDATE t SET s1 = s1 + 2;
END IF;
END; //
因为参数parameter1值等于0,UPDATE语句被履行.假如parameter1值为NULL,则下一条UPDATE语句将被履行目前表t中有两行,他们都包含值5,所以假如我们调用p12,两行的值会变成6.
7.
mysql> CALL p12(0)//
Query OK, 2 rows affected (0.28 sec)
mysql> SELECT * FROM t//
+------+
| s1 |
+------+
| 6 |
| 6 |
+------+
2 rows in set (0.01 sec)
后果也是我们所盼望的那样.
上一页 [1] [2] [3] [4] [5] [6] 下一页
CASE 指令
1.
CREATE PROCEDURE p13 (IN parameter1 INT)
BEGIN
DECLARE variable1 INT;
SET variable1 = parameter1 + 1;
CASE variable1
WHEN 0 THEN INSERT INTO t VALUES (17);
WHEN 1 THEN INSERT INTO t VALUES (18);
ELSE INSERT INTO t VALUES (19);
END CASE;
END; //
假如需求举行更多条件真假的判断我们可以利用CASE语句.CASE语句利用和IF一样简单.
我们可以参考上面的例子:
2.
mysql> CALL p13(1)//
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM t//
+------+
| s1 |
+------+
| 6 |
| 6 |
| 19 |
+------+
3 rows in set (0.00 sec)
履行历程后,传入值1,如上面例子,值19被插入到表t中.
Question
问题
问题: CALL p13(NULL) //的作用是什么?
另一个:这个CALL语句做了那些行动?
你可以通过履行后察看SELECT做了什么,也可以按照代码判断,在5秒内做出.
Answer
答案
mysql> CALL p13(NULL)//
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM t//
+------+
| s1 |
+------+
| 6 |
| 6 |
| 19 |
| 19 |
+------+
4 rows in set (0.00 sec)
答案是当你调用p13时,MySQL插入了另一条包含数值19的记录.缘由是变量variable1的值为NULL,CASE语句的ELSE部份就被履行了.但愿这对大家有意义.假如你答复不出来,没有问题,我们可以持续向下走.
上一页 [1] [2] [3] [4] [5] [6] 下一页
Loops 循环语句
WHILE ... END WHILE
LOOP ... END LOOP
REPEAT ... END REPEAT
GOTO
下面我们将会成立一些循环.我们有三种尺度的循环方法:
WHILE循环,LOOP循环以及REPEAT循环.还有一种非尺度的循环方法:GO TO(译者语:最好不要用吧,用了就使流程混乱).
WHILE ... END WHILE
CREATE PROCEDURE p14 ()
BEGIN
DECLARE v INT;
SET v = 0;
WHILE v < 5 DO
INSERT INTO t VALUES (v);
SET v = v + 1;
END WHILE;
END; //
这是WHILE循环的方法.我很喜好这种方法,它跟IF语句类似,因此不需求掌握很多新的语法.这里的INSERT和SET语句在WHILE和END WHILE之间,当变量v大于5的时刻循环将会退出.利用
"SET v = 0;"
语句使为了避免一个常见的错误,假如没有初始化,默许变量值为NULL,而NULL和任何值操作后果都为NULL.
WHILE ... END WHILE example
mysql> CALL p14()//
Query OK, 1 row affected (0.00 sec)
以上就是调用历程p14的后果不用关注系统返回是"one row affected"还是"five rows affected",因为这里的计数只对最后一个INSERT行动举行计数.
WHILE ... END WHILE example: CALL
mysql> select * from t; //
+------+
| s1 |
+------+
....
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
+------+
9 rows in set (0.00 sec)
调用后可以看到程序向数据库中插入了5行.
REPEAT ... END REPEAT
CREATE PROCEDURE p15 ()
BEGIN
DECLARE v INT;
SET v = 0;
REPEAT
INSERT INTO t VALUES (v);
SET v = v + 1;
UNTIL v >= 5
END REPEAT;
END; //
这是一个REPEAT循环的例子,功效和前面WHILE循环一样.辨别在于它在履行后查抄后果,而WHILE则是履行前查抄.(译者语:大概平等于DO WHILE吧)
REPEAT ... END REPEAT: look at the UNTIL: UNTIL的作用
CREATE PROCEDURE p15 ()
BEGIN
DECLARE v INT;
SET v = 0;
REPEAT
INSERT INTO t VALUES (v);
SET v = v + 1;
UNTIL v >= 5 <--
END REPEAT;
END; //
注意到UNTIL语句背面没有分号,在这里可以不写分号,当然你加上额外的分号更好.
REPEAT ... END REPEAT: calling :调用
mysql> CALL p15()//
Query OK, 1 row affected (0.00 sec)
mysql> SELECT COUNT(*) FROM t//
+----------+
| COUNT(*) |
+----------+
| 14 |
+----------+
1 row in set (0.00 sec)
我们可以看到调用p15历程后又插入了5行记录
LOOP ... END LOOP
CREATE PROCEDURE p16 ()
BEGIN
DECLARE v INT;
SET v = 0;
loop_label: LOOP
INSERT INTO t VALUES (v);
SET v = v + 1;
IF v >= 5 THEN
LEAVE loop_label;
END IF;
END LOOP;
END; //
以上是LOOP循环的例子.
LOOP循环不需求初始条件,这点和WHILE循环类似,同时它又和REPEAT循环一样也不需求完毕条件.
LOOP ... END LOOP: with IF and LEAVE 包含IF和LEAVE的LOOP循环
CREATE PROCEDURE p16 ()
BEGIN
DECLARE v INT;
SET v = 0;
loop_label: LOOP
INSERT INTO t VALUES (v);
SET v = v + 1;
IF v >= 5 THEN <--
LEAVE loop_label;
END IF;
END LOOP;
END; //
在循环内部加入IF语句,在IF语句中包含LEAVE语句.这里LEAVE语句的意义是脱离循环.
LEAVE的语法是LEAVE加循环语句标号,关于循环语句的标号问题我会在背面进一步讲授.
LOOP ... END LOOP: calling :调用
mysql> CALL p16()//
Query OK, 1 row affected (0.00 sec)
mysql> SELECT COUNT(*) FROM t//
+----------+
| COUNT(*) |
+----------+
| 19 |
+----------+
1 row in set (0.00 sec)
调用历程p16后,后果是另5行被插入表t中.
上一页 [1] [2] [3] [4] [5] [6] 下一页
Labels 标号
CREATE PROCEDURE p17 ()
label_1: BEGIN
label_2: WHILE 0 = 1 DO LEAVE label_2; END
WHILE;
label_3: REPEAT LEAVE label_3; UNTIL 0 =0
END REPEAT;
label_4: LOOP LEAVE label_4; END LOOP;
END; //
最后一个循环例子中我利用了语句标号.目前这里有一个包含4个语句标号的历程的例子.我们可以在BEGIN、WHILE、REPEAT大概LOOP语句前利用语句标号,语句标号只能在合理的语句前面利用.因此"LEAVE label_3"意味着脱离语句标号名定义为label_3的语句或复合语句.
End Labels 标号完毕符
CREATE PROCEDURE p18 ()
label_1: BEGIN
label_2: WHILE 0 = 1 DO LEAVE label_2; END
WHILE label_2;
label_3: REPEAT LEAVE label_3; UNTIL 0 =0
END REPEAT label_3 ;
label_4: LOOP LEAVE label_4; END LOOP
label_4 ;
END label_1 ; //
你也可以在语句完毕时利用语句标号,和在开首时利用一样.这些标号完毕符并非非常有效.
它们是可选的.假如你需求,他们必须和开始定义的标号名字一样当然为了有杰出的编程习惯,便利他人阅读,最好还是利用标号完毕符.
LEAVE and Labels 跳出和标号
CREATE PROCEDURE p19 (parameter1 CHAR)
label_1: BEGIN
label_2: BEGIN
label_3: BEGIN
IF parameter1 IS NOT NULL THEN
IF parameter1 = 'a' THEN
LEAVE label_1;
ELSE BEGIN
IF parameter1 = 'b' THEN
LEAVE label_2;
ELSE
LEAVE label_3;
END IF;
END;
END IF;
END IF;
END;
END;
END;//
LEAVE
语句使程序跳出复杂的复合语句.
ITERATE
迭代假如目标是ITERATE(迭代)语句的话,就必须用到LEAVE语句
CREATE PROCEDURE p20 ()
BEGIN
DECLARE v INT;
SET v = 0;
loop_label: LOOP
IF v = 3 THEN
SET v = v + 1;
ITERATE loop_label;
END IF;
INSERT INTO t VALUES (v);
SET v = v + 1;
IF v >= 5 THEN
LEAVE loop_label;
END IF;
END LOOP;
END; //
上一页 [1] [2] [3] [4] [5] [6] 下一页
ITERATE
(迭代)语句和LEAVE语句一样也是在循环内部的循环引用,它有点像C语言中的"Continue",一样它可以呈目前复合语句中,引用复合语句标号,ITERATE(迭代)意思是重新开始复合语句.
那我们启动并察看下面这个循环,这是个需求迭代历程的循环:
ITERATE: Walking through the loop
深化循环
CREATE PROCEDURE p20 ()
BEGIN
DECLARE v INT;
SET v = 0;
loop_label: LOOP <--
IF v = 3 THEN
SET v = v + 1;
ITERATE loop_label;
END IF;
INSERT INTO t VALUES (v);
SET v = v + 1;
IF v >= 5 THEN
LEAVE loop_label;
END IF;
END LOOP;
END; //
让这个已经定义了标号的循环运行起来.
ITERATE: Walking through the loop
CREATE PROCEDURE p20 ()
BEGIN
DECLARE v INT;
SET v = 0;
loop_label: LOOP
IF v = 3 THEN <--
SET v = v + 1;
ITERATE loop_label;
END IF;
INSERT INTO t VALUES (v);
SET v = v + 1;
IF v >= 5 THEN
LEAVE loop_label;
END IF;
END LOOP;
END; //
v的值变成3,然后我们把它增添到4.
ITERATE: walking through the loop
CREATE PROCEDURE p20 ()
BEGIN
DECLARE v INT;
SET v = 0;
loop_label: LOOP
IF v = 3 THEN
SET v = v + 1;
ITERATE loop_label; <--
END IF;
INSERT INTO t VALUES (v);
SET v = v + 1;
IF v >= 5 THEN
LEAVE loop_label;
END IF;
END LOOP;
END; //
然后开始ITERATE(迭代)历程.
ITERATE: walking through the loop
CREATE PROCEDURE p20 ()
BEGIN
DECLARE v INT;
SET v = 0;
loop_label: LOOP <--
IF v = 3 THEN
SET v = v + 1;
ITERATE loop_label;
END IF;
INSERT INTO t VALUES (v);
SET v = v + 1;
IF v >= 5 THEN
LEAVE loop_label;
END IF;
END LOOP;
END; //
这里的ITERATE(迭代)让循环又回到了循环的头部.
ITERATE: walking through the loop
CREATE PROCEDURE p20 ()
BEGIN
DECLARE v INT;
SET v = 0;
loop_label: LOOP
IF v = 3 THEN
SET v = v + 1;
ITERATE loop_label;
END IF;
INSERT INTO t VALUES (v);
SET v = v + 1;
IF v >= 5 THEN
LEAVE loop_label; <--
END IF;
END LOOP;
END; //
当v的值变成5时,程序将履行LEAVE语句
ITERATE: walking through the loop
CREATE PROCEDURE p20 ()
BEGIN
DECLARE v INT;
SET v = 0;
loop_label: LOOP
IF v = 3 THEN
SET v = v + 1;
ITERATE loop_label;
END IF;
INSERT INTO t VALUES (v);
SET v = v + 1;
IF v >= 5 THEN
LEAVE loop_label;
END IF;
END LOOP;
END; // <--
LEAVE的后果就是跳出循环,使运行指令到达复合语句的最后一步.
GOTO
CREATE PROCEDURE p...
BEGIN
...
LABEL label_name;
...
GOTO label_name;
...
END;
MySQL的存储历程中可以利用GOTO语句.固然这不是尺度SQL语句,并且在这里成立标号的办法也和惯例中的不一样.由于为了和其他DBMS兼容,这个语句会慢被淘汰,所以我们在MySQL参考手册中没有说起.
Grand combination
大组合
CREATE PROCEDURE p21
(IN parameter_1 INT, OUT parameter_2 INT)
LANGUAGE SQL DETERMINISTIC SQL SECURITY INVOKER
BEGIN
DECLARE v INT;
label goto_label; start_label: LOOP
IF v = v THEN LEAVE start_label;
ELSE ITERATE start_label;
END IF;
END LOOP start_label;
REPEAT
WHILE 1 = 0 DO BEGIN END;
END WHILE;
UNTIL v = v END REPEAT;
GOTO goto_label;
END;//
上面例子中的语句包含了我们之前讲的全部语法,包含参数列表,特点参数,BEGIN/END块复合语句,变量声明,IF,WHILE,LOOP,REPEAT,LEAVE,ITERATE,GOTO.这是一个荒诞的存储历程,我不会运行它,因为里面有没有尽的循环.但是里面的语法却非常合理.这些是新的流程掌握和变量声明语句.下面我们将要接触更多新的东西.
未完待续...
上一页 [1] [2] [3] [4] [5] [6]
以上是“MySQL 5.0 新特点教程 存储历程:第三讲[MySQL防范]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:本文地址: | 与您的QQ/BBS好友分享! |