在伺服器對伺服器的遠端預存程序中處理錯誤

當您從用戶端的 SQL Server 本機執行個體執行遠端預存程序與批次時,您可能會遇到陳述式和批次中止錯誤:

  • 當陳述式中止錯誤發生時,將會結束造成錯誤的陳述式,但是遠端預存程序或批次的執行仍會繼續。

  • 當批次中止錯誤發生時,就會結束執行完整的遠端預存程序或批次。

  • 當遠端預存程序和批次在 TRY 區塊的範圍內執行時,可由 TRY…CATCH 建構處理批次中止錯誤。

源自陳述式與批次中止錯誤的遠端預存程序和批次的行為,端視本機伺服器的 SET XACT_ABORT 設定而定。

SET XACT_ABORT 是 OFF

如果在本機伺服器中 SET XACT_ABORT 是 OFF,則在遠端預存程序中的陳述式中止錯誤,會由本機伺服器以陳述式中止錯誤傳播至用戶端。只會結束造成錯誤的陳述式。用戶端會接收與陳述式中止錯誤相對應的錯誤訊息。另外,如果遠端預存程序執行到它完成為止,@@ERROR 會傳回 0。如果在 TRY 區塊的範圍內發生錯誤,執行會繼續,但不會叫用 CATCH 區塊。

本機伺服器會將遠端預存程序中的批次中止錯誤傳播至用戶端。呼叫預存程序的 EXECUTE 陳述式會結束,但是包含 EXECUTE 陳述式的批次或預存程序會繼續執行。因此,@@ERROR 會傳回對應至結束遠端預存程序的錯誤之錯誤碼,而預存程序的傳回值則是 NULL。當產生錯誤的遠端預存程序在本機伺服器的 TRY 區塊範圍內執行時,該錯誤會造成控制項傳遞遠端伺服器上最後一個錯誤的資訊至 CATCH 區塊。

當您疑難排解錯誤時,請從 TRY…CATCH 建構的 TRY 區塊內執行遠端預存程序。如果遠端預存程序尚未成功完成,執行會跳至本機伺服器上關聯的 CATCH 區塊,其中包含遠端伺服器上最後一個錯誤的資訊。如果遠端預存程序已成功完成,會在本機伺服器上的 TRY 區塊內繼續執行,而且可以使用遠端預存程序的傳回值。

您也可以在 TRY 區塊的範圍外執行遠端預存程序時,在遠端預存程序結束時檢查 @@ERROR,以判斷遠端預存程序是否已經完成。如果 @@ERROR 是 0,表示遠端預存程序已成功執行,而且可以使用預存程序的傳回值。如果 @@ERROR 不是 0,則表示遠端預存程序未成功完成,而且無法使用預存程序的傳回值。

SET XACT_ABORT 是 ON

如果在本機伺服器上 SET XACT_ABORT 是 ON,設定會傳播至連結伺服器。在遠端預存程序中的所有陳述式和批次中止錯誤,會轉換為本機伺服器中的批次中止錯誤。因此,呼叫遠端預存程序的批次或預存程序之執行會與遠端預存程序一起結束。當產生錯誤的遠端預存程序在本機伺服器的 TRY 區塊範圍內執行時,該錯誤會造成控制項傳遞遠端伺服器上最後一個錯誤的資訊至 CATCH 區塊。

在 TRY 區塊的範圍外執行遠端預存程序時,您將無法檢查 @@ERROR 的值來判斷是否已發生批次錯誤,因為在 EXECUTE 陳述式後面的陳述式未執行。因此您應該從 TRY…CATCH 建構的 TRY 區塊內執行遠端預存程序。如果遠端預存程序尚未成功完成,執行會跳至本機伺服器上關聯的 CATCH 區塊,其中包含遠端伺服器上最後一個錯誤的資訊。如果遠端預存程序成功完成,會在本機伺服器上的 TRY 區塊內繼續執行,而且可以使用遠端預存程序的傳回值。

RAISERROR 與 TRY…CATCH

從遠端預存程序內呼叫嚴重性小於 20 的 RAISERROR,將會造成在遠端伺服器上產生陳述式中止錯誤。在本機伺服器上的 TRY…CATCH 建構只會處理遠端批次中止錯誤。如果遠端預存程序呼叫嚴重性小於 20 的 RAISERROR,而且遠端預存程序是限定在本機伺服器的 TRY 區塊範圍內執行時,RAISERROR 並不會造成控制項傳遞至 TRY…CATCH 建構的 CATCH 區塊中。然而,在遠端伺服器上嚴重性為 20 或更大值的 RAISERROR 將會中斷連接,在本機伺服器上的執行將會傳遞至 CATCH 區塊。