【发布时间】:2014-04-05 15:12:43
【问题描述】:
我正在运行一个 SP 来更新帐户中的余额。这是SP代码:
CREATE procedure UpdateBalance(@LedgerID as int,@TransDate as DateTime,@Neg as smallint) as
Begin
Declare @OpenBal as decimal(12,2)
Select Top 1 @OpenBal=Balance From Trans Inner Join TransGroup On Trans.TGID=TransGroup.TGID And TransDate<@TransDate Where LedgerID=@LedgerID Order By TransDate,TransGroup.TGID;
With CTE as
(Select TransGroup.TGID,LedgerID,Amount,Balance,Sum(Amount) Over(Order By TransDate,TransGroup.TGID) as 'Total' From Trans Inner Join TransGroup On Trans.TGID=TransGroup.TGID And TransDate>=@TransDate Where LedgerID=@LedgerID)
Update CTE Set Balance=Total+@OpenBal
End
SP 运行良好,并从@TransDate 开始更新帐户余额。
@Neg 参数当前未使用,其值为 0、-1 或 1。
如果@Neg 参数不为零,如果正在更新的Total+@OpenBal 值的符号与@Neg 参数的符号不匹配,我希望SP 失败。
例如,如果 @Neg 为 1,则 Balance 应始终为正数,如果在任意行变为负数,SP 将失败。
当然,一个简单的解决方案是将 Update 语句放入事务中,运行 Select 语句来检查负余额,然后相应地提交或回滚事务。但我想知道是否有办法在Update CTE Set Balance=Total+@OpenBal 语句中引发错误,以便它自动回滚所有内容。
我尝试了类似的方法 - 但了解到不能在 Case 语句中调用 Throw。
Update CTE Set Balance=Case @Neg When 0 Then Total+@OpenBal When 1 Then Case When Total+@OpenBal<0 Then Throw Else Total+@OpenBal End When -1 Then Case When Total+@OpenBal<0 Then Throw Else Total+@OpenBal End End
有什么想法吗?
【问题讨论】:
-
另一个选项是通过更新触发器处理余额
-
触发器只会为更新语句运行一次,而不是每行 - 即使您正在更新整个表...其次,触发器将在所有行都更新后触发。第三,触发器不能执行回滚。
-
好的。我通过用“ABCD”替换 Throw 来管理它。这将导致 varchar 转换错误,并且更新语句将失败。我对此不太满意,因为我想要一个自定义错误。无论如何,它现在必须做......
标签: sql-server tsql stored-procedures sql-server-2012 common-table-expression