如何使用递归函数更新表?

时间:2010-09-27 15:56:18

标签: sql sql-server recursion user-defined-functions

这是this question的后续行动。

不允许函数写入数据库,但是如果我想在每次调用函数时更新记录,特别是递归函数,该怎么办?

目前,我有一个带ID的函数并返回一个浮点数。我想使用给定的ID和返回的float更新表。通常,可以使用简单的存储过程来调用该函数,然后进行更新。我的函数是递归的,因此解决方案并不那么简单......

我正在考虑尝试这样做:

  • 创建递归函数,使其将表作为参数
  • 如果表为null,则创建它;否则,将表复制到一个新变量(因为它只是readonly)
  • 在进行递归调用之前更新函数中复制的表,并将副本传递给函数
  • 最后,返回完整的表格(不知道我将如何“知道”它是否完整)
  • 从使用返回的表进行多次更新的存储过程调用此函数

在我尝试这样的事情之前,我正在寻找替代方案。似乎以前已经做过。

1 个答案:

答案 0 :(得分:6)

任何递归实现都是T-SQL迟早会遇到@@NESTLEVEL cap

  

您可以嵌套存储过程和   托管代码引用最多32个   水平。嵌套级别增加   一个当被调用的存储过程   或托管代码引用开始   执行并减少一个时   被调用的存储过程或托管   代码引用完成执行。   试图超过最大值32   嵌套水平导致整体   呼叫链失败。

但是我们从CS101知道,任何递归算法都可以在堆栈的帮助下实现为迭代算法。因此,您需要一个表来充当堆栈(有关相关讨论,请参阅Using Tables as Queues)。使用存储过程而不是函数,因为在T-SQL中“函数”是特殊的(基本上是数据访问路径)并且不允许修改数据。每当你想到'function'(如在C / C ++ / C#函数或方法中)时,你真的需要一个存储过程。您不能从过程返回'tables',因此输出必须是您在其中写入结果的表。

所有这些只是理论,因为你没有提供实际问题,只是对问题类型的描述。如果我们知道真正的问题,我们可能会说存储过程是否有意义,是否使用游标是否正常,是否使用#temp表等等等等。所有这些只是考虑普通的香草算法。如果添加数据大小的考虑因素和并发问题,事情就会变得非常毛茸茸。