2015-10-13 38 views
0

考慮以下存儲過程:如何從SQL RaiseError而不是「Msg 50000」返回實際的錯誤消息?

CREATE PROCEDURE [dbo].[MergeCustomers] 
    @CustomerToKeep UNIQUEIDENTIFIER 
    , @CustomerToDelete UNIQUEIDENTIFIER 
AS 
    DECLARE @ERROR_MSG NVARCHAR(MAX) 
     , @SEVERITY INT 
     , @STATE INT 
     , @CustomError NVARCHAR(MAX); 

    BEGIN TRY 
     BEGIN TRANSACTION; 

     BEGIN 
      SET NOCOUNT ON; 

      BEGIN 
       /* 1. Check for potential Duplicate Subscriptions if they exist, rollback. */ 
       IF EXISTS (SELECT [S].[SubscriptionType] 
          FROM [dbo].[subscribers] AS [S] 
          WHERE ([S].[UserID] = @CustomerToKeep) 
            OR ([S].[UserID] = @CustomerToDelete) 
          GROUP BY [S].[SubscriptionType] 
          HAVING COUNT([S].[SubscriptionType]) > 1) 
        BEGIN 
         SET @CustomError = N'Customers cannot be merged. These customers have potential duplicate' 
           + 'subscriptions, and might need a refund to occur before merging. ' 
           + 'Please contact Support.' + ERROR_MESSAGE(); 
         RAISERROR(@CustomError, 16, 1) --change to > 10 
        END 
      END     
     END 

     COMMIT TRANSACTION; 

    END TRY 

    BEGIN CATCH 
     DECLARE @SQLErrorMessage NVARCHAR(2048); 
     SET @SQLErrorMessage = ERROR_MESSAGE(); 
     RAISERROR (@SQLErrorMessage, 16, 1); 

     IF @@TRANCOUNT > 0 
      ROLLBACK TRANSACTION; 
    END CATCH 
GO 

什麼我試圖做的是提出一個自定義錯誤,並返回錯誤時引發,但所有我得到當我運行PROC是:

消息50000,級別16,狀態1,過程MergeCustomers,90號線

我將調用從C#WinForm的這裏面PROC,我想確實有可用的真實錯誤消息,所以我知道這是什麼它是,並且可以顯示給用戶。我也想在Proc中測試它。

我期待,當我運行這個進程內的SQL作爲

EXECUTE [dbo].[MergeCustomers] @CustomerToKeep = '6B88274A-38F0-11D5-9D8A-00A0C9D7DEE4', -- uniqueidentifier 
    @CustomerToDelete = '06AB5121-A87D-11D5-9D9D-00A0C9D7DEE4' -- uniqueidentifier 

上看到一條消息,如:

客戶不能合併。這些客戶有潛在的重複訂閱,並且在合併之前可能需要退款。請聯繫支持。

回答

1

從第一SET語句刪除+ ERROR_MESSAGE()。此時沒有錯誤消息,因此引發的錯誤消息是NULL

CREATE PROCEDURE [dbo].[MergeCustomers] 
    @CustomerToKeep uniqueidentifier 
    , @CustomerToDelete uniqueidentifier 
AS 
    DECLARE @ERROR_MSG nvarchar(MAX) 
     , @SEVERITY int 
     , @STATE int 
     , @CustomError nvarchar(MAX); 

    BEGIN TRY 
     BEGIN TRANSACTION; 

     SET NOCOUNT ON; 

     IF EXISTS (SELECT [S].[SubscriptionType] 
        FROM [dbo].[subscribers] AS [S] 
        WHERE ([S].[UserID] = @CustomerToKeep) 
          OR ([S].[UserID] = @CustomerToDelete) 
        GROUP BY [S].[SubscriptionType] 
        HAVING COUNT([S].[SubscriptionType]) > 1) 
      BEGIN 
       SET @CustomError = N'Customers cannot be merged. These customers have potential duplicate' 
        + 'subscriptions, and might need a refund to occur before merging. ' 
        + 'Please contact Support.'; 
       RAISERROR(@CustomError, 16, 1); --change to > 10 
      END; 

     COMMIT TRANSACTION; 

    END TRY 

    BEGIN CATCH 
     DECLARE @SQLErrorMessage nvarchar(2048); 
     SET @SQLErrorMessage = ERROR_MESSAGE(); 
     RAISERROR (@SQLErrorMessage, 16, 1); 

     IF @@TRANCOUNT > 0 
      ROLLBACK TRANSACTION; 
    END CATCH; 
GO 
+0

因此,最內層的錯誤消息,我應該刪除ERROR_MESSAGE(),因爲它是空的。我明白了。什麼斯科特「 - 改爲> 10」?你是否在說要改變嚴重程度?這些更改將允許我在sql中運行proc並查看消息輸出嗎? – PKD

+0

嚴重性16是好的。我只包含了原始代碼中的評論,但我會編輯我的答案以將其刪除以避免混淆。 –

+0

對不起 - 我在與婆婆一起吃晚飯的時候寫下了評論。我可能已經(當然)有點分心。 :) – PKD

1

您可以簡單地使用try catch塊並捕獲Exception並使用它的Message屬性。它包含您的錯誤消息。

要測試你可以創建這個過程:

Create PROCEDURE [dbo].[TestProcedure] 
AS 
RAISERROR(N'Some error', 16, 1) 
RETURN 0 

那麼這種方式測試:

var connection = new SqlConnection(@"Your connection string"); 
var command = new SqlCommand("dbo.TestProcedure", connection); 
command.CommandType = CommandType.StoredProcedure; 
try 
{ 
    connection.Open(); 
    command.ExecuteNonQuery(); 
    connection.Close(); 
} 
catch (Exception ex) 
{ 
    MessageBox.Show(ex.Message); 
} 
finally 
{ 
    if (connection.State == ConnectionState.Open) 
     connection.Close(); 
} 
+0

我明白了。這解決了它的c#方面。 – PKD

+0

它也完全爲您提供瞭如何在SQL Server端完成您的工作。 :) –

相關問題