MySQL程序vs函数,什么时候用?

wydwbb8l  于 12个月前  发布在  Mysql
关注(0)|答案(7)|浏览(141)

我在看MySQL的过程和函数,它们之间真实的区别是什么?
它们看起来很相似,但功能有更多的限制。
我可能错了,但似乎过程可以做任何事情,而且比函数做得更多。为什么/什么时候我会使用过程而不是函数?

7z5jn7bk

7z5jn7bk1#

过程和函数之间最常见的区别是它们的调用方式不同,目的也不同:

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

创建例程的方法对于过程和函数来说有些不同:

1.过程参数可以定义为仅输入、仅输出或两者兼有。这意味着过程可以使用输出参数将值传递回调用方。这些值可以在CALL语句之后的语句中访问。函数只有输入参数。因此,尽管过程和函数都可以有参数,但过程参数声明与函数的声明不同。

  • 函数返回值,因此在函数定义中必须有一个RETURNS子句来指示返回值的数据类型。此外,函数体内必须至少有一个RETURN语句来向调用方返回值。RETURNS和RETURN不出现在过程定义中。
  • 要调用存储过程,请使用CALL statement。要调用存储函数,请在表达式中引用它。该函数在表达式计算期间返回一个值。
  • 一个过程是使用CALL语句调用的,并且只能使用输出变量传递回值。一个函数可以像任何其他函数一样从语句内部调用(即,通过调用函数的名称),并且可以返回标量值。
  • 将参数设置为IN、OUT或INOUT仅对PROCEDURE有效。对于FUNCTION,参数始终被视为IN参数。

如果参数名前没有给出关键字,则默认为IN参数。**存储函数的参数前不带IN、OUT或INOUT。**所有函数参数都被视为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语句的结果相同。但是,这样的结果集的内容不能直接在表达式中使用。

存储例程(指存储过程和存储函数)**与特定的数据库相关联,就像表或视图一样。**当您删除数据库时,数据库中的任何存储例程也会被删除。
**存储过程和函数不共享相同的命名空间。**在数据库中可能有同名的过程和函数。
在存储过程中可以使用动态SQL,但不能在函数或触发器中使用。

SQL预准备语句(EXECUTE,DEALLOCATE EXECUTE)可以在存储过程中使用,但不能在存储函数或触发器中使用。因此,存储函数和触发器不能使用动态SQL(将语句构造为字符串,然后执行它们)。(MySQL存储例程中的动态SQL)

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

1.(* 这一点是从博客文章复制的。)存储过程是预编译的执行计划,而函数不是。函数在运行时解析和编译。存储过程,存储为数据库中的伪代码,即编译形式。
1.(
我不确定这一点。*)
存储过程具有安全性,减少了网络流量,而且我们可以在任何数量的应用程序中同时调用存储过程。reference
1.函数通常用于计算,而过程通常用于执行业务逻辑。
1.函数不能影响数据库的状态(函数中不允许执行显式或隐式提交或回滚的语句),而存储过程可以使用提交等方式影响数据库的状态。
参考:J.1.对存储的进程和触发器的限制
1.函数不能使用FLUSH语句,而存储过程可以。
1.存储函数不能是递归的,而存储过程可以是递归的。注意:默认情况下,递归存储过程是禁用的,但可以在服务器上通过将max_sp_recursion_depth服务器系统变量设置为非零值来启用。有关详细信息,请参见第5.2.3节“系统变量”。
1.在存储的函数或触发器中,不允许修改调用函数或触发器的语句已经使用(用于阅读或写入)的表。

备注:虽然某些限制通常适用于存储函数和触发器,但不适用于存储过程,但如果从存储函数或触发器中调用存储过程,则这些限制确实适用于存储过程。例如,尽管可以在存储过程中使用FLUSH,但不能从存储函数或触发器调用此类存储过程。

yx2lnoni

yx2lnoni2#

你不能将存储过程与普通的SQL混合在一起,而存储函数可以。
例如,如果get_foo()是一个过程,则SELECT get_foo(myColumn) FROM mytable无效,但如果get_foo()是一个函数,则可以这样做。代价是函数比过程有更多的限制。

atmip9wb

atmip9wb3#

一个显著的区别是,您可以在SQL查询中包含function,但stored procedures只能通过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)

字符串
Sproc示例:

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)

bbuxkriu

bbuxkriu4#

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

pepwfjgg

pepwfjgg5#

存储过程可以递归调用,但存储函数不能

uklbhaso

uklbhaso6#

除了上面给出的答案,我想补充一点,
函数可以与其他函数和表达式组合使用,也可以以嵌套的方式使用(简而言之,它们可以以非常复杂的形式使用,以完成我们想要的工作)。
同样的事情可以在过程中实现,但是在过程中我们必须完成在该过程中完成的所有工作,这意味着在一个整体的时尚代码中。(而在函数中,可以为每个任务;可以实现一个新的函数)。所以最后我们可以通过使用不同函数的组合来完成任务。

drkbr07n

drkbr07n7#

当不使用transaction和/或不返回多个值时,应该使用function
当使用transaction和/或返回多个值时,应该使用procedure

一个函数:

  • BEGIN ... END statement中可以有零个或多个SQL语句。* 没有BEGIN ... END语句的语句会出错。
  • 可以只有一个RETURN语句,不会将变量更改为$$而不会出错。
  • 可以从调用者那里得到零个或多个带有零个或多个参数的值,然后返回一个值给调用者。
  • 必须使用RETURN语句返回一个值。
  • 必须是DETERMINISTICNOT DETERMINISTIC。* 如果其中任何一个没有设置,则NOT DETERMINISTIC被隐式设置。
  • 可以有SELECT INTO statement,但不能有SELECT没有INTO,否则有错误。
  • 可以有local variablesuser-defined variables。* 我的答案解释了局部变量和用户定义变量。
  • 不能有交易,否则会有错误。
  • 默认情况下是原子的,所以如果有错误,它会自动回滚。
  • 我的答案和the doc详细解释了一个函数。

一个过程:

  • BEGIN ... END语句中可以有零个或多个SQL语句。* 没有BEGIN ... END语句的语句会出错。
  • 可以只有一个语句,而没有BEGIN ... END语句,没有错误地将$$更改为$$
  • 可以有多个参数,包括INOUTINOUT,也可以没有这些参数。
  • 可以从调用方获取零个或多个带有零个或多个ININOUT参数的值。
  • 可以使用OUTINOUT参数向调用者返回零个或多个值。
  • 可以有局部变量和用户定义的变量。
  • 可以进行交易。
  • 不能有RETURN语句,否则会出现错误。
  • 默认情况下不是原子的,所以如果有错误,它不会自动回滚。* My answer详细解释。
  • 我的答案和the doc详细解释了一个程序。

相关问题