簡體   English   中英

錯誤檢查 SQL 中的動態存儲過程

[英]Error Checking Dynamic Stored Procedure in SQL

我有一個帶有 3 個不同UPDATE查詢的存儲過程。

我希望每個查詢都返回一個值。

如果它失敗,我不希望過程COMMIT ,我希望它ROLLBACK告訴我三個存儲過程中的哪一個失敗了。

我可以在非動態中做到這一點,但由於某種原因,相同的規則似乎不適用於動態查詢。

這是我的代碼和我的嘗試:

ALTER PROCEDURE [dbo].[ASP_XXNominalBalanceUPDATE]
     @ORGCODE VARCHAR(6),
     @NewNominal INT,
     @OldNominal INT,
     @BalMonth CHAR(6),
     @Amt Decimal(12,2),
     @FINPERIODNR INT,
     @InvDetailID INT,
     @Err INT = 0,
     @Rows INT = 0
AS 
BEGIN TRAN
    SET NOCOUNT ON;

    DECLARE @SQL NVARCHAR(MAX)
    SET @SQL = N'SET @Err = 0
                 SET @Rows = 0

                 UPDATE CostCodeBalance' + @ORGCODE + ' COB
                 SET COB.' + @BalMonth + '  = (SELECT COB.' + @BalMonth + ' FROM CostCodeBalance' + @ORGCODE + ' COB WHERE COB.CostCode = @OldNominal AND COB.FinPeriodNr = @FINPERIODNR) + @Amt
                 WHERE COB.CostCode = @OldNominal AND COB.FinPeriodNr = @FINPERIODNR

                 SELECT @Err = @@Error, @Rows = @@ROWCOUNT

                 UPDATE CostCodeBalance' + @ORGCODE + ' COB
                 SET COB.' + @BalMonth + ' = (SELECT COB.' + @BalMonth + ' FROM CostCodeBalance' + @ORGCODE + ' COB WHERE COB.CostCode = @NewNominal AND COB.FinPeriodNr = @FINPERIODNR) - @Amt
                 WHERE COB.CostCode = @NewNominal AND COB.FinPeriodNr = @FINPERIODNR

                 SELECT @Err = @@Error, @Rows = @@ROWCOUNT

                 UPDATE Posting' + @ORGCODE + ' PO
                 SET Nominal = @NewNominal
                 WHERE PO.Deleted = 0 AND PO.OrderRecNo = @InvDetailID AND PO.OrderType = ''SI''

                 SELECT @Err = @@Error, @Rows = @@ROWCOUNT;';

    -- Check if succeeded to find.
    If @Err = 0 AND @Rows > 0 
        COMMIT TRAN
    ELSE
        ROLLBACK TRAN

    EXEC sp_executesql @sql, N'@ORGCODE VARCHAR(6), @NewNominal INT, @OldNominal INT, @BalMonth CHAR(6), @Amt Decimal(12,2), @FINPERIODNR INT, @InvDetailID INT, @Err INT, @Rows INT', 
                             @ORGCODE, @NewNominal, @OldNominal, @BalMonth, @Amt,  @FINPERIODNR, @InvDetailID, @Err, @Rows; 

這當然是完全未經測試的,但這應該會給你一個正確的方向。

ALTER PROCEDURE [dbo].[ASP_XXNominalBalanceUPDATE]
     @ORGCODE VARCHAR(6),
     @NewNominal INT,
     @OldNominal INT,
     @BalMonth CHAR(6),
     @Amt Decimal(12,2),
     @FINPERIODNR INT,
     @InvDetailID INT

AS 
BEGIN TRAN
SET NOCOUNT ON;
DECLARE @SQL NVARCHAR(MAX)

declare @RowCount1 int
    , @RowCount2 int
    , @RowCount3 int

BEGIN TRANSACTION

BEGIN TRY
    SET @SQL = N'
    UPDATE ccb
    SET ' + @BalMonth + '  = ccb.' + @BalMonth + ' + @AMT '
    + ' FROM CostCodeBalance' + @ORGCODE + ' ccb 
    WHERE ccb.CostCode = @OldNominal AND ccb.FinPeriodNr = @FINPERIODNR'

    EXEC sp_executesql @sql, N'@ORGCODE VARCHAR(6), @OldNominal INT, @BalMonth CHAR(6), @Amt Decimal(12,2), @FINPERIODNR INT', 
                               @ORGCODE, @OldNominal, @BalMonth, @Amt, @FINPERIODNR; 
    set @RowCount1 = @@ROWCOUNT                       


    set @SQL = N'
    UPDATE ccb
    SET ' + @BalMonth + ' = ccb.' + @BalMonth + ' - @Amt'
    + ' FROM CostCodeBalance' + @ORGCODE + ' ccb 
    WHERE ccb.CostCode = @NewNominal AND ccb.FinPeriodNr = @FINPERIODNR'

    EXEC sp_executesql @sql, N'@ORGCODE VARCHAR(6), @OldNominal INT, @BalMonth CHAR(6), @Amt Decimal(12,2), @FINPERIODNR INT', 
                               @ORGCODE, @OldNominal, @BalMonth, @Amt, @FINPERIODNR; 
    set @RowCount2 = @@ROWCOUNT                       

    set @SQL = N'
    UPDATE Posting' + @ORGCODE 
    + 'SET Nominal = @NewNominal
    WHERE Deleted = 0 AND Posting' + @ORGCODE + '.OrderRecNo = @InvDetailID AND OrderType = ''SI'''

    EXEC sp_executesql @sql, N'@ORGCODE VARCHAR(6), @NewNominal INT, @InvDetailID INT', 
                                @ORGCODE, @NewNominal, @InvDetailID; 

    set @RowCount3 = @@ROWCOUNT

    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    --Add some logic here for what you want returned when an error occurs.
    ROLLBACK TRANSACTION
END CATCH    

這是我的答案,以防萬一其他人想知道我是如何解決它的。

CREATE PROCEDURE [dbo].[ASP_XXNominalBalanceUPDATE]
     @ORGCODE VARCHAR(6),
     @NewNominal INT,
     @OldNominal INT,
     @BalMonth CHAR(6),
     @Amt Decimal(12,2),
     @FINPERIODNR INT,
     @InvDetailID INT

AS 
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON; --IMPORTANT TO TURN THIS ON
DECLARE @SQL NVARCHAR(MAX)

    BEGIN TRAN

        ------RUN THE 1st PROCEDURE------
        SET @SQL = N'
        UPDATE CCB
        SET CCB.' + @BalMonth + '  = (SELECT CCB2.' + @BalMonth + ' FROM CostCodeBalance' + @ORGCODE + ' CCB2 
                                      WHERE CCB2.CostCode = @OldNominal AND CCB2.FinPeriodNr = @FINPERIODNR) + @Amt
        FROM CostCodeBalance' + @ORGCODE + ' CCB
        WHERE CCB.CostCode = @OldNominal AND CCB.FinPeriodNr = @FINPERIODNR;';

        EXEC sp_executesql @sql, N'@ORGCODE VARCHAR(6), @NewNominal INT,@OldNominal INT, @BalMonth CHAR(6), @Amt Decimal(12,2), @FINPERIODNR INT, @InvDetailID INT', 
                                    @ORGCODE, @NewNominal, @OldNominal, @BalMonth, @Amt,  @FINPERIODNR, @InvDetailID; 

        ------TEST IF ANYTHING WAS UPDATED------
        IF  @@ROWCOUNT = 0 GOTO ERR_HANDLER -- IF NOT THEN ROLLBACK AND RETURN ERROR

        ------RUN THE 2nd PROCEDURE------
        SET @SQL = N'
        UPDATE CCB
        SET CCB.' + @BalMonth + ' = (SELECT CCB2.' + @BalMonth + ' FROM CostCodeBalance' + @ORGCODE + ' CCB2 
                                     WHERE CCB2.CostCode = @NewNominal AND CCB2.FinPeriodNr = @FINPERIODNR) - @Amt
        FROM CostCodeBalance' + @ORGCODE + ' CCB
        WHERE CCB.CostCode = @NewNominal AND CCB.FinPeriodNr = @FINPERIODNR;';

        EXEC sp_executesql @sql, N'@ORGCODE VARCHAR(6), @NewNominal INT,@OldNominal INT, @BalMonth CHAR(6), @Amt Decimal(12,2), @FINPERIODNR INT, @InvDetailID INT', 
                                    @ORGCODE, @NewNominal, @OldNominal, @BalMonth, @Amt,  @FINPERIODNR, @InvDetailID; 

        ------TEST IF ANYTHING WAS UPDATED------
        IF  @@ROWCOUNT = 0 GOTO ERR_HANDLER -- IF NOT THEN ROLLBACK AND RETURN ERROR

        ------RUN THE 3rd PROCEDURE------
        SET @SQL = N'
        UPDATE PO
        SET Nominal = @NewNominal
        FROM Posting' + @ORGCODE + ' PO
        WHERE PO.Deleted = 0 AND PO.OrderRecNo = @InvDetailID AND PO.OrderType = ''SI'';';

        EXEC sp_executesql @sql, N'@ORGCODE VARCHAR(6), @NewNominal INT,@OldNominal INT, @BalMonth CHAR(6), @Amt Decimal(12,2), @FINPERIODNR INT, @InvDetailID INT', 
                                    @ORGCODE, @NewNominal, @OldNominal, @BalMonth, @Amt,  @FINPERIODNR, @InvDetailID; 

        ------TEST IF ANYTHING WAS UPDATED------                        
        IF  @@ROWCOUNT = 0 GOTO ERR_HANDLER -- IF NOT THEN ROLLBACK AND RETURN ERROR

    COMMIT TRAN 
    RETURN 0 


ERR_HANDLER:
PRINT 'Unexpected error occurred!' --RETURN AN ERROR MESSAGE
ROLLBACK TRAN 
RETURN 1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM