存储过程带输出参数 vs 表值函数?

3

如果我需要一个返回2个参数的成员(sp或func),哪种方法更好:

CREATE PROCEDURE Test
   @in INT,
   @outID INT OUT,
   @amount DECIMAL OUT
AS
BEGIN
   ...
END

或者

CREATE FUNCTION Test
(
   @in INT
)
RETURNS @ret TABLE (outID INT, amount DECIMAL)
AS
BEGIN
   ...
END

考虑到结果将传递给另一个存储过程,每种方法的优缺点是什么:

EXEC Foobar @outID, @outAmount
7个回答

3

表值函数只能在单个SELECT语句的作用域内使用。它不能执行DML,捕获异常等操作。

另一方面,它可以返回一个集合,可立即与同一查询中的另一个记录集连接。

如果您使用DML或不需要在基于集合的语句中使用输出参数,请使用存储过程;否则创建TVF


+1 对于两者的优缺点给出了最好的解释,但由于问题“仅”想在存储过程中使用返回值而不是Select语句(他们以后可能会后悔),因此存储过程胜出。 - JeffO
这里的 DML 是什么意思? - Niklas

1

使用带有输出参数的存储过程,您只能返回两个值:@outID@amount

使用表值函数,您可以返回整个一组(outID, amount)tuples。此外,表值函数可以在查询中允许使用表达式或视图表达式的任何地方使用,例如:

SELECT dbo.Test(1) AS TestValues

那么如果我需要返回正好2个值,我不需要使用函数吗? - abatishchev
是的,在你的情况下,看起来表值函数可能是更好的选择。请注意,与存储过程不同,表值函数也可以在查询中使用。 - Daniel Vassallo

1
一个调用函数的存储过程 :-) 我想任何一种方法都适合你... 如果你的应用程序使用存储过程来查询数据库,那么保持一致可能是最好的选择... 如果你使用 ORM,则它可能无法识别函数... 任何一种方法都没错。
在我的某个应用程序中,我们更喜欢使用函数方法,给你提供另一个角度。
希望对你有所帮助。

1
我认为输出参数的方法是最理想的。这使得它更加自我说明,表明只有一个元组被期望,我认为这种方法可能更有效率。

1

如果我需要获取一张值的表格,那么我只会使用一个表格值函数。

如果你的输出中只有一行,则最好使用存储过程中的输出参数。

其中一个例外是,如果你的SP/UDF可以编写为单个SELECT语句 - 即内联函数 - 因为如果你需要将其与另一个查询的输出连接起来,SQL Server可以进行更好的优化。你现在可能不这样做,但编写内联UDF意味着如果将来有人以这种方式使用它,你就不会被慢如糖浆的查询和超时报告所困扰。

如果以上都不适用于你,那么出于上述原因,我会使用存储过程;你不希望在实际上不支持它们时创建集合语义的幻觉。


1

输出参数。

多语句表值函数难以追踪和调整。建议使用存储过程,因为它更容易进行故障排除。

此外,在UDF中您的操作是受限的。比如说,如果您需要添加日志记录或稍后调用扩展存储过程... 您不能使用UDF来实现这些功能。


0

我认为你更好的选择应该是SP,因为使用TBF(表值函数)需要通过迭代来获取值。

请记住,如果在SQL中遍历表,则需要使用CURSOR(它们并不太糟糕,但可能有点棘手)。


1
从test(@in)中选择@outid = outid; 有什么需要迭代的吗?如果存储过程基于业务逻辑返回单个值集,则表函数也可以这样做。 - JeffO

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