【问题标题】:Raise Error in Update Statement在更新语句中引发错误
【发布时间】: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


【解决方案1】:

您不能在 UPDATE 语句中引发自定义异常。

你有几个选择:

  1. 在更新时使用 INSTEAD OF 触发器。您可以根据需要阻止更新发生、抛出自定义错误等。
  2. 在此过程中,执行 Total + @OpenBal 计算并将它们插入到表变量中。选择无效值,如果你发现一些你可以抛出一个自定义错误;否则,将您的表变量与您需要的任何其他内容连接起来并进行更新

通过插入错误值进行抛出是一种黑客行为,并且该错误会使任何使用您的存储过程的人感到困惑。看起来您的代码有错误。

不过我有点好奇 - 为什么要单独存储符号,然后验证另一个值是否具有相同的符号?你的设计听起来很不规范。

【讨论】:

  • 谢谢埃里克。我想尽可能避免触发。但这可能是我唯一的选择了。表变量也是另一个不错的选择。我需要单独存储符号的原因:在会计中,我们可以有可以有负余额的账户(比如客户的应收账款账户),也可以有永远不能有负余额的账户(比如现金-在手帐户)。因此,根据账户类型,有必要检查所有结果余额是否正确。
  • 您是否研究过 CHECK 约束?您可以在 CHECK 约束中使用 UDF,这让您可以使用它们做很多事情。例如,请参见此处 - sqlmag.com/t-sql/using-udf-check-constraint-validate-column
猜你喜欢
  • 2021-07-22
  • 2023-02-13
  • 2012-10-11
  • 1970-01-01
  • 2016-03-31
  • 1970-01-01
  • 1970-01-01
  • 2011-05-03
  • 2016-12-18
相关资源
最近更新 更多