WhyMySQLStatementsareLegalinaProcedureBody 什么MySQL语句在存储过程体中是合法的?"/>
好学IT学院:IT信息技术分享交流平台
来源:互联网  作者:mysql-AB;翻译:陈朋奕  发布时间:2006-12-24  ★★★加入收藏〗〖手机版
摘要: WhyMySQLStatementsareLegalinaProcedureBody 什么MySQL语句在存储过程体中是合法的?…

6.
CREATE PROCEDURE p2 ()
LANGUAGE SQL
NOT DETERMINISTIC
SQL SECURITY DEFINER
COMMENT ''
SELECT CURRENT_DATE, RAND() FROM t //

上面过程跟下面语句是等效的:
CREATE PROCEDURE p2 ()
SELECT CURRENT_DATE, RAND() FROM t //

特征子句也有默认值,如果省略了就相当于:
LANGUAGE SQL NOT DETERMINISTIC SQL SECURITY DEFINER COMMENT ''

Digressions一些题外话

Digression:
  调用p2()//的结果
mysql> call p2() //
+--------------+-----------------+

CURRENT_DATE

RAND()


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

2004-11-09

0.7822275075896


+--------------+-----------------+
1 row in set (0.26 sec)
Query OK, 0 rows affected (0.26 sec)
  当调用过程p2时,一个SELECT语句被执行返回我们期望获得的随机数。
  Digression: sql_mode unchanging
  不会改变的

sql_mode
mysql> set sql_mode='ansi' //
mysql> create procedure p3()select'a'

'b'//
mysql> set sql_mode=''//
mysql> call p3()//
+------------+

'a'

'b'


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

ab


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

MySQL在过程创建时会自动保持运行环境。例如:我们需要使用两条竖线来连接字符串但是这只有在sql mode为ansi的时候才合法。如果我们将sql mode改为non-ansi,不用担心,它仍然能工作,只要它第一次使用时能正常工作。

Exercise 练习

Question
  问题
  如果你不介意练习一下的话,试能否不看后面的答案就能处理这些请求。
  创建一个过程,显示`Hello world`。用大约5秒时间去思考这个问题,既然你已经学到了这里,这个应该很简单。当你思考问题的时候,我们再随机选择一些刚才讲过的东西复习:
  DETERMINISTIC
  (确定性)子句是反映输出和输入依赖特性的子句…调用过程使用CALL过程名(参数列表)方式。好了,我猜时间也到了。

Answer
  答案
  好的,答案就是在过程体中包含
"SELECT 'Hello, world'"
  语句
  MySQL
mysql> CREATE PROCEDURE p4 () SELECT 'Hello, world' //
Query OK, 0 rows affected (0.00 sec)
mysql> CALL p4()//
+--------------+

Hello, world


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

Hello, world


+--------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)

Parameters 参数

让我们更进一步的研究怎么在存储过程中定义参数
  1. CREATE PROCEDURE p5
  () ...
  2. CREATE PROCEDURE p5
  ([IN] name data-type) ...
  3. CREATE PROCEDURE p5
  (OUT name data-type) ...
  4. CREATE PROCEDURE p5
  (INOUT name data-type) ...

回忆一下前面讲过的参数列表必须在存储过程名后的括号中。上面的第一个例子中的参数列表是空的,第二个例子中有一个输入参数。这里的词IN可选,因为默认参数为IN(input)。

第三个例子中有一个输出参数,第四个例子中有一个参数,既能作为输入也可以作为输出。
  IN example 输入的例子
mysql> CREATE PROCEDURE p5(p INT) SET @x = p //
Query OK, 0 rows affected (0.00 sec)
mysql> CALL p5(12345)//
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @x//
+-------+

@x


+-------+

12345


+-------+
1 row in set (0.00 sec)

这个IN的例子演示的是有输入参数的过程。在过程体中我将会话变量x设定为参数p的值。然后调用过程,将12345传入参数p。选择显示会话变量@x,证明我们已经将参数值12345传入。
  OUT example 输出的例子
mysql> CREATE PROCEDURE p6 (OUT p INT)
-> SET p = -5 //
mysql> CALL p6(@y)//
mysql> SELECT @y//
+------+

@y


+------+

-5


+------+

这是另一个例子。这次的p是输出参数,然后在过程调用中将p的值传入会话变量@y中。

在过程体中,我们给参数赋值-5,在调用后我们可以看出,OUT是告诉DBMS值是从过程中传出的。
  同样我们可以用语句
"SET @y = -5;"

来达到同样的效果

Compound Statements 复合语句

现在我们展开的详细分析一下过程体:
CREATE PROCEDURE p7 ()
BEGIN
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语句块和Pascal语言中的BEGIN/END是基本相同的,和C语言的框架是很相似的。我们可以使用块去封装多条语句。在这个例子中,我们使用了多条设定会话变量的语句,然后完成了一些insert和select语句。如果你的过程体中有多条语句,那么你就需要BEGIN/END块了。BEGIN/END块也被称为复合语句,在这里你可以进行变量定义和流程控制。