Answers:
不能将存储过程与普通SQL混合使用,而可以将存储函数与普通SQL混合使用。
例如,SELECT get_foo(myColumn) FROM mytable
如果get_foo()
是一个过程,则无效,但如果get_foo()
是一个函数,则可以这样做。代价是功能比程序具有更多的限制。
过程和函数之间最普遍的区别是,它们以不同的目的和不同的目的被调用:
例程创建的语法在过程和功能上有所不同:
函数返回值,因此函数定义中必须有RETURNS子句,以指示返回值的数据类型。此外,函数体内必须至少有一个RETURN语句才能将值返回给调用方。RETURNS和RETURN不会出现在过程定义中。
要调用存储过程,请使用CALL statement
。要调用存储的函数,请在表达式中引用它。该函数在表达式求值期间返回一个值。
使用CALL语句调用过程,并且只能使用输出变量传回值。可以像其他任何函数一样从语句内部调用函数(即,通过调用函数名称),并且可以返回标量值。
将参数指定为IN,OUT或INOUT仅对PROCEDURE有效。对于功能,参数始终被视为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预准备语句(PREPARE,EXECUTE,DEALLOCATE PREPARE)可以在存储过程中使用,但不能用于存储函数或触发器。因此,存储的函数和触发器不能使用动态SQL(将语句构造为字符串然后执行它们)。(MySQL中的动态SQL存储例程)
功能和存储过程之间还有一些更有趣的区别:
(这是从博客文章中复制的。)存储过程是预编译的执行计划,而函数没有。在运行时解析和编译的函数。存储过程,作为伪代码存储在数据库中,即编译形式。
(我不确定这一点。)
存储过程具有安全性并减少了网络流量,而且我们可以以任何方式调用存储过程。一次申请。参考
函数通常用于计算,而过程通常用于执行业务逻辑。
函数不能影响数据库的状态(函数中不允许进行显式或隐式提交或回滚的语句),而存储过程可以使用提交等来影响数据库的状态。
参考:J.1。对存储的例程和触发器的限制
函数不能使用FLUSH语句,而存储过程可以。
存储函数不能是递归的,而存储过程可以是递归的。注意:递归存储过程默认情况下处于禁用状态,但是可以通过将max_sp_recursion_depth服务器系统变量设置为非零值来在服务器上启用。有关更多信息,请参见第5.2.3节“系统变量”。
在存储的函数或触发器内,不允许修改调用该函数或触发器的语句已在使用(用于读取或写入)的表。很好的例子:如何在MYSQL中删除时更新同一张表?
注意:尽管一些限制通常适用于存储函数和触发器,但不适用于存储过程,但是如果从存储函数或触发器中调用它们,则这些限制确实适用于存储过程。例如,尽管可以在存储过程中使用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)
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)
RETURNS CHAR(50) DETERMINISTIC
?
RETURNS CHAR(50)
什么类型的数据的状态将被退回。该RETURN CONCAT(...
是正在返回的数据。两者都需要。的DETERMINISTIC
是需要状态下的基础数据也不会被修改。