MySQL的存储过程与function,我会用什么时候?

我在看MySQL存储过程和函数。 真正的区别是什么?

他们似乎是相似的,但function有更多的限制。

我可能是错的,但似乎一个存储过程可以做所有事情,更多的存储function可以。 为什么/什么时候我会使用一个过程vs一个函数?

您不能将存储过程与普通SQL混合使用,而使用存储function则可以。

例如SELECT get_foo(myColumn) FROM mytable如果get_foo()是一个过程,则无效,但如果get_foo()是一个函数,则可以这样做。 价格是function比程序有更多的局限性。

程序和函数之间最常见的区别在于它们被调用的方式不同,目的不同:

  1. 一个过程不会返回一个值。 而是使用CALL语句调用它来执行操作,例如修改表或处理检索到的logging。
  2. 在expression式中调用一个函数,并直接向expression式中使用的调用方返回一个值。
  3. 您不能用CALL语句调用函数,也不能在expression式中调用过程。

例程创build的语法在程序和函数上有所不同:

  1. 过程参数可以定义为仅input,仅输出或两者。 这意味着一个过程可以通过使用输出参数将值传递给调用者。 这些值可以在CALL语句后面的语句中访问。 函数只有input参数。 因此,虽然程序和函数都可以有参数,但程序参数声明与函数不同。
  2. 函数返回值,所以在函数定义中必须有一个RETURNS子句来表示返回值的数据types。 此外,函数体内必须至less有一个RETURN语句才能将值返回给调用者。 过程定义中不显示RETURNS和RETURN。

    • 要调用存储过程,请使用CALL statement 。 要调用存储的函数,请在expression式中引用它。 该函数在expression式评估期间返回一个值。

    • 使用CALL语句调用过程,并且只能使用输出variables传回值。 一个函数可以像在其他函数中那样从一个语句中调用(也就是通过调用该函数的名字),并且可以返回一个标量值。

    • 将参数指定为IN,OUT或INOUT仅对于PROCEDURE有效。 对于function,参数始终被视为IN参数。

    如果在参数名称前没有给出关键字,则默认为IN参数。 存储函数的参数不在IN,OUT或INOUT之前。 所有的function参数都被视为IN参数。

要定义存储过程或函数,分别使用CREATE PROCEDURE或CREATE FUNCTION:

 CREATE PROCEDURE proc_name ([parameters]) [characteristics] routine_body CREATE FUNCTION func_name ([parameters]) RETURNS data_type // diffrent [characteristics] routine_body 

存储过程(不是函数)的MySQL扩展是一个过程可以生成一个结果集,或者甚至是多个结果集,调用者的处理方式与SELECT语句的结果相同。 但是,这样的结果集的内容不能直接在expression式中使用。

存储例程 (指存储过程和存储函数) 与特定数据库相关联,就像表或视图一样。 删除数据库时,数据库中的任何存储例程也将被删除。

存储过程和函数不共享相同的名称空间。 在数据库中可能有一个相同名称的过程和函数。

在存储过程中,可以使用dynamicSQL,但不能在函数或触发器中使用。

SQL准备语句(PREPARE,EXECUTE,DEALLOCATE PREPARE)可用于存储过程,但不能存储函数或触发器。 因此,存储的函数和触发器不能使用dynamicSQL(您将语句构造为string,然后执行它们)。 (MySQL存储例程中的dynamicSQL)

FUNCTION和STORED PROCEDURE之间的一些更有趣的区别:

  1. 这一点是从博客复制 。 )存储过程是预编译的执行计划,其中function不是。 函数在运行时parsing和编译。 存储过程,存储为数据库中的伪代码即编译forms。

  2. 我不确定这一点。
    存储过程具有安全性,减less了networkingstream量,同时我们还可以调用存储过程。 一次申请。 参考

  3. 函数通常用于计算,而程序通常用于执行业务逻辑。

  4. 函数不能影响数据库的状态(在函数中不允许显式或隐式提交或回滚的语句)存储过程可以使用提交等影响数据库的状态
    参考: J.1。 存储例程和触发器的限制

  5. 函数不能使用FLUSH语句,而存储过程可以。

  6. 存储函数不能recursion而存储过程可以。 注意:recursion存储过程默认是禁用的,但可以通过将max_sp_recursion_depth服务器系统variables设置为非零值来在服务器上启用。 有关更多信息,请参见第5.2.3节“系统variables” 。

  7. 在已存储的函数或触发器中,不允许通过调用函数或触发器的语句来修改已经在使用(用于读取或写入)的表。 良好的例子: 如何更新MYSQL删除相同的表?

注意 :虽然一些限制通常适用于已存储的函数和触发器,但不适用于存储过程,但如果存储过程是从存储的函数或触发器中调用的,则这些限制适用于存储过程。 例如,尽pipe可以在存储过程中使用FLUSH,但是这样的存储过程不能从存储的函数或触发器中调用。

一个显着的区别是你可以在你的SQL查询中包含一个函数 ,但是只能用CALL语句调用存储过程 :

UDF示例:

 CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN CONCAT('Hello, ',s,'!'); Query OK, 0 rows affected (0.00 sec) CREATE TABLE names (id int, name varchar(20)); INSERT INTO names VALUES (1, 'Bob'); INSERT INTO names VALUES (2, 'John'); INSERT INTO names VALUES (3, 'Paul'); SELECT hello(name) FROM names; +--------------+ | hello(name) | +--------------+ | Hello, Bob! | | Hello, John! | | Hello, Paul! | +--------------+ 3 rows in set (0.00 sec) 

例如:

 delimiter // CREATE PROCEDURE simpleproc (IN s CHAR(100)) BEGIN SELECT CONCAT('Hello, ', s, '!'); END// Query OK, 0 rows affected (0.00 sec) delimiter ; CALL simpleproc('World'); +---------------------------+ | CONCAT('Hello, ', s, '!') | +---------------------------+ | Hello, World! | +---------------------------+ 1 row in set (0.00 sec) 

存储过程和用户​​定义函数的区别

在这里输入图像描述

存储的函数可以在查询中使用。 然后,您可以将其应用于每一行或WHERE子句中。

一个过程使用CALL查询来执行。