T-SQL-具有默认参数的功能


155

我有这个脚本:

CREATE FUNCTION dbo.CheckIfSFExists(@param1 INT, @param2 BIT = 1 )
RETURNS BIT
AS
BEGIN
    IF EXISTS ( bla bla bla )
        RETURN 1;
    RETURN 0;
END
GO

我想以这种方式在过程中使用它:

IF dbo.CheckIfSFExists( 23 ) = 0
    SET @retValue = 'bla bla bla';

但是我得到了错误:

为过程或函数dbo.CheckIfSFExists提供的参数数量不足。

为什么不起作用?

Answers:


227

你必须这样称呼它

SELECT dbo.CheckIfSFExists(23, default)

来自Technet

当函数的参数具有默认值时,在调用函数时必须指定关键字DEFAULT才能检索默认值。此行为与在存储过程中使用具有默认值的参数不同,在存储过程中,省略参数也意味着使用默认值。通过使用EXECUTE语句调用标量函数时,此行为是一个例外。使用EXECUTE时,不需要DEFAULT关键字。


80
看到这个我很沮丧。我在default这里没有得到概念的好处...我现在需要去改变所有地方。
LCJ 2014年

8
@Lijo,您仍然可以获得不重复每次调用的具体默认值的优点。
弗雷德里克

9
由于我们不允许重叠,因此“默认”的可用性受到限制,因此最好的方法通常是使用后缀(例如,CheckIfSFExistsEX)创建带有附加参数的新扩展版本,并将原始功能更改为使用“默认”参数调用扩展版本。这样,所有现有代码都可以工作,并且您只有一个地方可以维护。
Eske Rahn

39

您可以通过三种方式来调用它-带参数,DEFAULT和EXECUTE

SET NOCOUNT ON;

DECLARE
@Table  SYSNAME = 'YourTable',
@Schema SYSNAME = 'dbo',
@Rows   INT;

SELECT dbo.TableRowCount( @Table, @Schema )

SELECT dbo.TableRowCount( @Table, DEFAULT )

EXECUTE @Rows = dbo.TableRowCount @Table

SELECT @Rows

11
为什么DEFAULT在select中需要关键字,而在execute中却可以省略关键字?这很糟糕:/希望有一天会解决。
Misiu,

@Misiu,它不需要“修复”。那是设计使然。我阅读了许多替代方法,以实现“理想的”目标,即仅需调用一个函数而无需指定每个参数即可,但是我没有清楚地解释为什么需要这样做。代码应该清晰易懂,并且要实现这一目标,编码人员必须始终意识到:“嘿,您正在调用的函数确实具有该参数和其他参数,而这些参数恰好具有默认值。请不要忘记默认值可能会更改”。因此,IMO,这是一件好事“坏事”。
古斯塔沃·平沙德

16

使用用户定义的函数,即使它们具有默认值,也必须声明每个参数。

以下将成功执行:

IF dbo.CheckIfSFExists( 23, default ) = 0
    SET @retValue = 'bla bla bla;

-1

解决此问题的一种方法是使用带有输出参数的存储过程。

exec sp_mysprocname @返回值输出,@firstparam = 1,@ secondparam = 2

默认情况下,您不会传递给存储过程本身中设置的默认值的值。您可以从输出变量中获取结果。


1
通常,将函数更改为存储过程不是一个好的解决方案,因为不能从查询中调用存储过程,但是可以从查询中调用存储过程。
刀片

是的,但是并非所有代码块都需要在查询中调用。已经证明sql没有一种很好的方法来处理函数的默认值(使用default关键字几乎与添加值一样多)。这不是一个好的通用解决方案,但是在某些用例中效果很好。
Jereme Guenther

人们一直在记下来,但是我坚持下去。如果您需要一个可重用的代码块(在查询内部不会被调用),并且希望具有默认值的真正可选参数具有灵活性,那么存储过程仍然比函数更好。
Jereme Guenther

1
使用存储过程并不意味着使用它们而不是使用函数,而是意味着将存储过程用作函数的包装器。我经常使用这种技术。在默认的关键字现在隐藏在proc中。我认为这个想法很好。如果需要,它还使我可以设置更复杂的默认值-与函数分开,可以将其保留为更纯净的状态。
J布赖恩·普莱斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.