当前位置:七道奇文章资讯数据防范MySQL防范
日期:2011-05-02 15:44:00  来源:本站整理

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防范]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
  • Windows 搭配 IIS7 PHP MySQL 环境
  • mysql Out of memory (Needed 16777224 bytes)的错误办理
  • mysql提醒[Warning] Invalid (old?) table or database name问题的办理办法
  • mysql启用skip-name-resolve情势时呈现Warning的处理办法
  • mysql启用skip-name-resolve情势时呈现Warning的处理办法
  • MySQL Order By语法介绍
  • <b>MySQL ORDER BY 的实现解析</b>
  • mysql数据库插入速度和读取速度的调整记录
  • MySQL Order By索引优化办法
  • MySQL Order By用法分享
  • mysql #1062 –Duplicate entry ''1'' for key ''PRIMARY''
  • MySQL Order By Rand()效率解析
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .