2015-11-12 54 views
2

我有3個不同的UPDATE查詢的存儲過程。錯誤檢查SQL中的動態存儲過程

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

如果失敗我不想讓過程到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; 
+2

MySQL或MS SQL Server?不要標記不涉及的產品。 – jarlh

+0

這裏肯定有一些問題。檢查@@錯誤和@@ ROWCOUNT每次都會被第三個查詢覆蓋。我會將它分成三個動態的sql調用,以便可以控制它。另外,如果你爲你的表使用了一個別名,你的動態sql會更容易閱讀,因爲你不需要一直在前面附加ORGCODE。 –

+0

@SeanLange是不是可以在一個程序中完成?我有很多場景,我在一個過程中有多個查詢 – Justin

回答

0

這是我的答案,我最終只是爲了防止其他人想知道我是如何解決它的。

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 
1

當然,這是完全未經測試,但是這應該給你在正確的方向輕推。

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  
+0

不太好用,但很好推動:) – Justin

+0

我覺得它不能正常工作,但很高興知道它讓你去。 –