MySQL存储过程是否可以有默认参数?

85

我已经谷歌过这个问题,但一直得到“不可能”的答案,但是这些文章的日期都是在2005-2007年之间,所以我想知道是否有所更改。下面是一个代码示例:

CREATE PROCEDURE `blah`
(
  myDefaultParam int = 0 -- This breaks the code for some reason
)
BEGIN
  -- Do something here
END

解决方案之一是传递 null,然后检查 null 并设置变量。我不想这样做,也不应该这样做。如果这是真的,那么 MySql 的开发人员需要醒醒了,因为我可以在 MSSQL 上做更多的事情。


1
在MySQL存储过程中编写可选参数 - Patrick Allaert
MariaDB 有同样的问题吗? - Webber Depor
6个回答

91

目前仍然不可能。


9
有没有任何方法可以解决呢?比如检查参数是否为空,然后给它一个默认值? - papaiatis
1
@papaiatis 是的,你可以添加一个if语句,参见我在下面的另一篇帖子。 - Dive50
3
我不知道为什么下面的@Dive50提供的有用的解决方法没有成为被采纳的答案,我将要实施这个方法因为我遇到了同样的问题。 - bokov
4
所以我讨厌MySQL。这么基本的东西还没有。 - Kamran Shahid
2
不可能使用建议的语法,但传递 NULL,然后使用 IFNULL 完全可行,并且可以实现完全相同的效果。 - Hans
显示剩余2条评论

58

我们通过在存储过程中添加简单的IF语句来解决这个限制。实际上,每当我们想要将默认值保存到数据库中时,我们传递一个空字符串。

CREATE DEFINER=`test`@`%` PROCEDURE `myProc`(IN myVarParam VARCHAR(40))
BEGIN
  IF myVarParam = '' THEN SET myVarParam = 'default-value'; END IF;

  ...your code here...
END

12
为什么不使用“null”呢? - Pacerier
2
这展示了你可以给予MySQL多少爱,而在SQL中你只需写上 "param_name int(11) = NULL" ... 谢谢Oracle。 - Sebastien H.

38
SET myParam = IFNULL(myParam, 0);

说明:IFNULL(expression_1, expression_2)

IFNULL 函数返回 expression_1,如果 expression_1 不是 NULL;否则返回 expression_2。在使用的上下文中,IFNULL 函数会根据需要返回字符串或数字。


2
这是更有效的方法来完成它。 - KD.S.T.

12
如果你查看最新版MySQL的CREATE PROCEDURE Syntax,你会发现存储过程参数只能包含IN/OUT/INOUT说明符、参数名称和类型。

因此,在最新版MySQL中仍然不支持默认值。

6

很遗憾,MySQL不支持DEFAULT参数值,所以:

CREATE PROCEDURE `blah`
(
  myDefaultParam int DEFAULT 0
)
BEGIN
  -- Do something here
END

返回错误:

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right syntax to use 
near 'DEFAULT 0) BEGIN END' at line 3

为了解决这个限制,只需创建额外的过程来为原始过程分配默认值:
DELIMITER //

DROP PROCEDURE IF EXISTS blah//
DROP PROCEDURE IF EXISTS blah2//
DROP PROCEDURE IF EXISTS blah1//
DROP PROCEDURE IF EXISTS blah0//

CREATE PROCEDURE blah(param1 INT UNSIGNED, param2 INT UNSIGNED)
BEGIN
    SELECT param1, param2;
END;
//

CREATE PROCEDURE blah2(param1 INT UNSIGNED, param2 INT UNSIGNED)
BEGIN
    CALL blah(param1, param2);
END;
//

CREATE PROCEDURE blah1(param1 INT UNSIGNED)
BEGIN
    CALL blah2(param1, 3);
END;
//

CREATE PROCEDURE blah0()
BEGIN
    CALL blah1(4);
END;
//

然后,执行以下命令:
CALL blah(1, 1);
CALL blah2(2, 2);
CALL blah1(3);
CALL blah0();

将返回:

+--------+--------+
| param1 | param2 |
+--------+--------+
|      1 |      1 |
+--------+--------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

+--------+--------+
| param1 | param2 |
+--------+--------+
|      2 |      2 |
+--------+--------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

+--------+--------+
| param1 | param2 |
+--------+--------+
|      3 |      3 |
+--------+--------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

+--------+--------+
| param1 | param2 |
+--------+--------+
|      4 |      3 |
+--------+--------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

如果您确保只使用blah2()blah1()blah0()程序,则在将第三个参数添加到blah()过程时,您的代码将不需要立即更新。


1

不,MySQL 存储过程语法不支持此功能。

请随意在 bugs.mysql.com 提交一个功能请求。


2
从我之前提出的另一个问题中发布此内容: http://bugs.mysql.com/bug.php?id=15975 - aarona

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接