【问题标题】:TSQL Recursive Stored Procedure Addition not workingTSQL递归存储过程添加不起作用
【发布时间】:2015-02-21 11:16:36
【问题描述】:

我的存储过程有问题。它应该从给定位置添加所有子项、子项等的值并返回它。目前它返回的只是NULL

这是一个将使用存储过程的表的示例。

稍后我也想在存储过程中实现运算符 Bool。如果是NULL,则计算中忽略saldo。如果为 0,则负向使用 saldo,如果为 1,则正向使用 saldo。

id  pos             operpos     saldo   operator
-------------------------------------------------
1   blue            NULL        NULL    NULL
2   lightblue       blue        NULL    1
3   darkblue        blue        25.00   1
4   skyblue         lightblue   12.00   1
5   babyblue        lightblue   -12.00  0
6   greyblue        lightblue   22.00   1
7   royalblue       darkblue    121.00  1
8   navyblue        darkblue    20.00   1
9   sailorsblue     navyblue    23.00   0
10  captainsblue    navyblue    33.00   1

这是calctotal(darkblue) 的存储过程应该计算的:

darkblue        +25
 royalblue      +121
 navyblue       +20
  sailorsblue   -23 //because operator = 0
  captainsblue  +33
OUTPUT          176

这是我目前拥有的存储过程:

ALTER PROCEDURE [dbo].[calctotal]
        //DECLARE INPUT AND OUTPUT
       @number nvarchar(255),
       @total NUMERIC(20,2) OUTPUT
AS
BEGIN
     //DECLARE THE VARIABLES
     DECLARE @pos NVARCHAR(255) = NULL;
     DECLARE @saldo NUMERIC(20,2) =  NULL;
     DECLARE @tmptotal NUMERIC(20,2)
     DECLARE @tmptotal2 NUMERIC(20,2) = 0;

     //LOAD DATA INTO CURSOR
     DECLARE cur CURSOR LOCAL for
        SELECT pos, saldo  
        FROM test 
        WHERE operpos = @number

     //START CURSOR AND FETCH NEXT
     OPEN CUR

     FETCH NEXT FROM CUR INTO @pos, @tmptotal2

     //WHEN NEW ITEM HAS BEEN LOADED
     WHILE @@FETCH_STATUS = 0
     BEGIN
         //ADD VALUE TO TMPTOTAL
         SET @tmptotal = @tmptotal2 + @tmptotal;

         //RECURSIVE PART SO FUNCTION APPLIES TO CHILDREN
         EXEC calctotal @pos, @tmptotal;
     END;

     close cur
     deallocate cur

     //THE OUTPUT OF TOTAL IS SET TO THE VALUE OF THE VARIABLE
     SET @total = @tmptotal;
END

你们对代码可能有什么问题和/或如何纠正它有什么想法吗?对于如何实现运算符布尔值的任何提示,我将非常高兴!

提前感谢您的帮助

编辑:我使用的是 SQL Server 2012

【问题讨论】:

  • 首先,请不要使用 CURSORS !它们对生产非常不利,其次,您能否根据上述定义向我们提供您希望最终结果看起来如何的示例数据?目前很混乱。谢谢
  • @Claudio 很抱歉不清楚。我在帖子中添加了和进行计算。
  • @Claudio 我不确定我还能如何将层次结构中的所有值递归地获取到输出中。这就是我使用游标的原因。您对使用什么而不是游标有什么建议,以便解析每个子项的值?
  • 是的,我正在尝试提出解决方案,现在正在进行测试。

标签: database tsql stored-procedures recursion sql-server-2012


【解决方案1】:

试试这个:

;with cte as
(select pos, operpos, saldo, [operator], 0 as level
 from tbl
 where pos = 'darkblue'
 union all
 select t.pos,t.operpos, t.saldo, t.[operator], c.level + 1
 from tbl t 
 inner join cte c on c.pos = t.operpos
)

select sum (
case 
when [operator] = 0 then (-1 * saldo) 
when [operator] = 1 then saldo 
else 0 
end) as totalsum from cte

这是一个递归公用表表达式 (CTE),可从 SQL Server 2005 开始使用。我们基本上检索了根值“darkblue”的所有子项,然后根据operator 字段进行条件求和。您可以传递参数,而不是硬编码,如下所示:

...
where pos = @pos
...

请注意,这种方法将数据作为一个集合处理,无需手动处理光标。

Demo

【讨论】:

  • 谢谢你,太好了!最后一个问题。我可以在带有输入变量@colour 的存储过程中使用这个 CTE 并将这个变量也添加到 cte(其中 pos = @colour)吗?
  • 是的,当然。提出问题的提示 - 始终指定 RDBMS 的版本,因为功能可能取决于版本。例如,此解决方案不适用于 SQL Server 2000。
  • 感谢您的解决方案和提示!我很想支持你的回答,但我还没有资格。我正在使用 SQL Server 2012,所以这应该可以工作:)
猜你喜欢
  • 2016-04-04
  • 1970-01-01
  • 2015-08-08
  • 2020-03-28
  • 1970-01-01
  • 2010-10-30
  • 2013-11-13
相关资源
最近更新 更多