3

我正在運行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 [email protected] 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>[email protected] Where [email protected]) 
Update CTE Set [email protected] 
End 

的SP運行正常,並從@TransDate開始更新帳戶的餘額。

@Neg參數是當前未用並且將具有的任值爲0,-1或1

如果@Neg參數爲非零,我想和SP如果[email protected]值的符號爲失敗已更新與@Neg參數的符號不匹配。

例如,如果@Neg爲1,則Balance應始終爲正值,如果SP在任何行變爲負值,則SP應該失敗。

當然,一個簡單的解決方案是將Update語句放入事務中,運行Select語句來檢查負餘額,然後相應地提交或回滾事務。但我想知道是否有辦法在Update CTE Set [email protected]聲明中引發錯誤,以便它自動回滾所有內容。

我嘗試了這樣的事情 - 但得知Throw無法在Case聲明中調用。

Update CTE Set Balance=Case @Neg When 0 Then [email protected] When 1 Then Case When [email protected]<0 Then Throw Else [email protected] End When -1 Then Case When [email protected]<0 Then Throw Else [email protected] End End 

任何想法?

+1

另一種選擇是通過更新觸發器處理餘額 – Jayvee

+0

觸發器只會針對更新語句運行一次,而不是針對每一行 - 即使您正在更新整個表...其次,觸發器將在所有行已更新。第三,觸發器不能執行回滾。 – navigator

+0

好的。我用'ABCD'代替了Throw。這將導致varchar轉換錯誤,並且更新語句將失敗。我對此並不滿意,因爲我想要一個自定義錯誤。無論如何,它將不得不現在做... – navigator

回答

1

您不能在UPDATE語句中引發自定義異常。

您有幾種選擇:

  1. 上更新使用INSTEAD OF觸發器。你可以防止更新發生,如果你想要,拋出一個自定義的錯誤等。
  2. 在這個過程中,做你的Total + @OpenBal計算並將它們插入到一個表變量中。選擇無效值,如果你發現一些你可以拋出一個自定義錯誤;否則,加入你的表變量與任何你需要的,並做更新

通過插入錯誤的值投擲是一個黑客和錯誤將混淆使用存儲過程的任何人。它看起來像你的代碼有錯誤。

雖然我有點好奇 - 爲什麼要單獨存儲標記,然後驗證另一個值是否具有相同的符號?您的設計聽起來非規範化。

+0

謝謝埃裏克。我想盡可能避免觸發器。但它可能是我唯一的選擇。表變量也是另一個不錯的選擇。爲什麼我需要單獨存儲該標誌:在會計中,我們可以擁有可能具有負餘額的帳戶(如客戶的應收帳款),並且我們也可以擁有永遠不會有負餘額的帳戶(例如現金手中賬戶)。因此,根據賬戶類型,有必要檢查所有餘額是否正確。 – navigator

+0

你看過CHECK約束嗎?你可以在CHECK約束中使用UDF,這可以讓你對它們做很多事情。例如,看到這裏 - http://sqlmag.com/t-sql/using-udf-check-constraint-validate-column – Eric