• MySQL 5.0 新特征教程 存储过程:第二讲


     前导发轫:网海拾贝  




    作者:mysql AB;翻译:陈朋奕

      Why MySQL Statements are Legal in a Procedure Body
      什么MySQL语句在存储过程体中是合法的?

      什么样的SQL语句在Mysql存储过程中才是合法的呢?你可以确立一个包括INSERT, UPDATE,DELETE, SELECT, DROP, CREATE, REPLACE等的语句。你独一须要记着的是如果代码中包括MySQL扩大功效,那么代码将不能移植。在模范榜样SQL语句中:任何数据库界说言语都是合法的,如:

     

    CREATE PROCEDURE p () DELETE FROM t; //
      SET、COMMIT以及ROLLBACK也是合法的,如:
    CREATE PROCEDURE p () SET @x = 5; //

      MySQL的附加功效:任何数据垄断言语的语句都将合法。
    CREATE PROCEDURE p () DROP TABLE t; //

      MySQL扩大功效:间接的SELECT也是合法的:
    CREATE PROCEDURE p () SELECT 'a'; //

      特殊提一下,我将存储过程中包括DDL语句的功效称为MySQL附加功效的缘由是在SQL模范榜样中把这个界说为非中心的,即可选组件。

      在过程体中有一个束缚,就是不能有对例程或表垄断的数据库垄断语句。例如下面的例子就是不法的:
    CREATE PROCEDURE p1 ()
    CREATE PROCEDURE p2 () DELETE FROM t; //

      下面这些对MySQL 5.0来说全新的语句,过程体中是不法的:
    CREATE PROCEDURE, ALTER PROCEDURE, DROP PROCEDURE, CREATE FUNCTION,
    DROP FUNCTION, CREATE TRIGGER, DROP TRIGGER.

      不过你可以运用
    CREATE PROCEDURE db5.p1 () DROP DATABASE db5//

      可是近似
    "USE database"

      语句也是不法的,由于MySQL假定默许数据库就是过程的任务场合。

      Call the Procedure 挪用存储过程
      1.
      如今我们就可以挪用一个存储过程了,你所须要输出的全部就是CALL和你过程名以及一个括号再一次强调,括号是必须确当你挪用例子内里的p1过程时,结果是屏幕前去了t表的内容
    mysql> CALL p1() //
    ------
    | s1 |
    ------
    | 5 |
    ------
    1 row in set (0.03 sec)
    Query OK, 0 rows affected (0.03 sec)

      由于过程中的语句是
    "SELECT * FROM t;"

      2. Let me say that again, another way.
      其他完成体例
    mysql> CALL p1() //

      和下面语句的实验结果一样:
    mysql> SELECT * FROM t; //

      以是,你挪用p1过程就相当于你实验了下面语句:
    "SELECT * FROM t;"

      好了,次要的常识点"确立和挪用过程方法"曾经明晰了。我进展你能对本身说这相当简朴。可是很快我们就有一系列的操演,每次都加一条子句,可能厘革曾经存在的子句。那样在写复杂年夜部件前我们将会有良多可用的子句。

    Characteristics Clauses 特征子句
      1.
    CREATE PROCEDURE p2 ()
    LANGUAGE SQL <--
    NOT DETERMINISTIC <--
    SQL SECURITY DEFINER <--
    COMMENT 'A Procedure' <--
    SELECT CURRENT_DATE, RAND() FROM t //

      这里我给出的是一些能反响存储过程特征的子句。子句内容在括号之后,主体之前。这些子句都是可选的,他们有什么传染感动呢?

      2.
    CREATE PROCEDURE p2 ()
    LANGUAGE SQL <--
    NOT DETERMINISTIC
    SQL SECURITY DEFINER
    COMMENT 'A Procedure'
    SELECT CURRENT_DATE, RAND() FROM t //

      很好,这个LANGUAGE SQL子句是没有传染感动的。仅是为了剖析');下面过程的主体运用SQL言语编写。这条是系统默许的,但你在这里声明是有用的,由于某些DBMS(IBM的DB2)须要它,如果你存眷DB2的兼容结果最好照旧用上。此外,尔后或许会呈现除SQL外的其他言语支持的存储过程。

      3.
    CREATE PROCEDURE p2 ()
    LANGUAGE SQL
    NOT DETERMINISTIC <--
    SQL SECURITY DEFINER
    COMMENT 'A Procedure'
    SELECT CURRENT_DATE, RAND() FROM t //

      下一个子句,NOT DETERMINISTIC,是传递给系统的信息。这里一个确定过程的界说就是那些每次输出一样输出也一样的措施。在这个案例中,既然主体中含有SELECT语句,那前去肯定是未知的因此我们称其NOT DETERMINISTIC。可是MySQL内置的优化措施不会注意这个,至多在如今不注意。

      4.
    CREATE PROCEDURE p2 ()
    LANGUAGE SQL
    NOT DETERMINISTIC
    SQL SECURITY DEFINER <--
    COMMENT 'A Procedure'
    SELECT CURRENT_DATE, RAND() FROM t //
      下一个子句是SQL SECURITY,可以界说为SQL SECURITY DEFINER或SQL SECURITY INVOKER。
      这就进入了权限控制的领域了,固然我们在后背将会有测试权限的例子。
    SQL SECURITY DEFINER

      意味着在挪用时反省确立过程用户的权限(另一个选项是SQLSECURITY INVOKER)。
      如今而言,运用
    SQL SECURITY DEFINER

      指令通知MySQL效力器反省确立过程的用户就可以了,当过程曾经被挪用,就不反省实验挪用过程的用户了。而另一个选项(INVOKER)则是通知效力器在这一步仍旧要反省挪用者的权限。

      5.
    CREATE PROCEDURE p2 ()
    LANGUAGE SQL
    NOT DETERMINISTIC
    SQL SECURITY DEFINER
    COMMENT 'A Procedure' <--
    SELECT CURRENT_DATE, RAND() FROM t //

      COMMENT 'A procedure'
      是一个可选的正文剖析');。

      最初,正文子句会跟过程界说存储在一路。这个没有稳固的模范榜样,我在文中会指出没有稳固模范榜样的语句,不过侥幸的是这些在我们模范榜样的SQL中很少。

      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块也被称为复合语句,在这里你可以进行变量界说和流程控制。




    版权声明: 原创作品,应许转载,转载时请务必以超链接体例标明文章 原始来由 、作者信息和本声明。否则将清查执法责任。

  • 相关阅读:
    HDU 2602
    ZOJ 1074 最大子矩阵和
    POJ 3903
    最大子段和
    HDU 1052
    CodeForces 18C
    CodeForces 546B-Soldier and Badges
    UVA 11462-Age sort
    Codeforces Round #326 (Div. 2)-Duff in Love
    Codeforces Round #327 (Div. 2)-Wizards' Duel
  • 原文地址:https://www.cnblogs.com/zgqjymx/p/1975800.html
Copyright © 2020-2023  润新知