首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 進階教學 (八):預存程序回傳結果、錯誤處理與遠端程序呼叫完整實務

     編輯:關於SqlServer

本文為 SQL Server 入門系列第八篇,深入探討預存程序的三種回傳機制、系統化錯誤處理模式,以及跨伺服器的遠端程序呼叫設定與實作。

一、預存程序回傳結果的三種方式

1. 回傳結果集 (最常用)

透過 SELECT 陳述式直接輸出,來源可以是永久表、暫存表或區域變數。注意:預存程序無法直接存取另一個預存程序的結果集。

範例 A:從永久表回傳

USE pubs;
GO
CREATE PROCEDURE ap_CreateResultFromPermtable
AS
    SELECT au_lname FROM authors;
GO

範例 B:從區域變數回傳

USE pubs;
GO
CREATE PROCEDURE ap_CreateResultFromVariable
AS
    DECLARE @au_lname CHAR(20);
    SELECT @au_lname = au_lname FROM authors WHERE au_id = '172-32-1176';
    SELECT @au_lname;  -- 輸出變數內容
GO

2. 設定 OUTPUT 參數

參數宣告加上 OUTPUT,程序內修改值將在返回呼叫端後保持。適用於單一標量值回傳。

設定端

CREATE PROCEDURE ap_SetOutputVar @count INT OUTPUT
AS
    SELECT @count = COUNT(*) FROM authors;
GO

呼叫端取值

CREATE PROCEDURE ap_GetOutputVar
AS
    DECLARE @num INT;
    EXECUTE ap_SetOutputVar @num OUTPUT;
    PRINT 'The count is ' + CAST(@num AS VARCHAR);
GO

游標作為 OUTPUT 參數

游標只能 OUTPUT 不能輸入。需指定 VARYING 關鍵字支援結果集輸出:

CREATE PROCEDURE GetTitleCount @count_cursor CURSOR VARYING OUTPUT
AS
    SET @count_cursor = CURSOR FOR
        SELECT au_id, COUNT(*) FROM titleauthors GROUP BY au_id;
    OPEN @count_cursor;
GO

3. 透過 RETURN 回傳狀態碼

預存程序永遠回傳整數狀態 (預設 0 表成功)。自訂錯誤碼慣用 1~127,避免與系統保留碼衝突。

設定狀態碼

CREATE PROCEDURE ap_SetReturnStatus
AS
    DECLARE @count INT;
    SELECT @count = COUNT(*) FROM authors;
    IF @count = 0 RETURN 1;  -- 自訂錯誤碼
    ELSE RETURN 0;
GO

呼叫端檢查

CREATE PROCEDURE ap_GetReturnStatus
AS
    DECLARE @status INT;
    EXECUTE @status = ap_SetReturnStatus;
    IF @status = 1 PRINT 'No rows found';
    ELSE PRINT 'Successful';
GO

二、預存程序錯誤處理機制

核心系統變數:@@ERROR

  • 每個 T-SQL 陳述式執行後更新
  • 0 = 成功,非 0 = 錯誤號碼 (對應 sysmessages 表)
  • 關鍵特性:@@ERROR 只保留「最近一條」陳述式的狀態,必須立即檢查或存入變數

錯誤類型與處理策略

1. 資料庫相關錯誤 (違反約束、型別轉換失敗等)

CREATE PROCEDURE ap_TrapDatabaseError @return_code INT OUTPUT
AS
    UPDATE authors SET au_lname = 'Jackson' WHERE au_lname = 'Smith';
    IF @@ERROR <> 0
    BEGIN
        SELECT @return_code = @@ERROR;
        RETURN;  -- 立即結束,避免後續陳述式覆蓋 @@ERROR
    END
    SELECT @return_code = 0;
GO

2. 業務邏輯錯誤 (違反商業規則)

使用 RAISERROR 主動拋出使用者定義錯誤:

RAISERROR (msg_id | msg_str, severity, state [, argument ...])
[WITH option]
參數說明
msg_idsysmessages 表中訊息 ID (50001+ 為使用者自訂)
msg_str動態訊息字串 (類 C printf 格式)
severity嚴重等級 1~25 (19+ 需系統管理員權限)
state1~127,區分相同錯誤的不同觸發點

WITH 選項

  • LOG:寫入 SQL Server 錯誤記錄與 Windows 事件檢視器 (需 severity 19~25)
  • NOWAIT:立即送達用戶端
  • SETERROR:強制 @@ERROR = msg_id 或 50000

三、遠端預存程序呼叫 (RPC)

前置條件:雙向設定連結伺服器

  1. 展開 SSMS 物件總管 → 伺服器物件 → 連結伺服器
  2. 右鍵「新增連結伺服器」
  3. 啟用「允許其他 SQL Server 透過 RPC 連線」
  4. 設定「查詢逾時」秒數 (0 = 無限等待)
  5. 重啟 SQL Server 服務生效
  6. 對方伺服器同樣設定

呼叫語法

EXEC Server2.pubs.dbo.myproc;

格式:EXEC [連結伺服器].[資料庫].[擁有者].[程序名]

實務總結與建議

  • 結果集適合多列多行資料;OUTPUT 參數適合單一值/狀態;RETURN僅限整數狀態碼
  • 錯誤處理務必「即檢即存」,避免 @@ERROR 被後續陳述式覆蓋
  • 業務錯誤統一用 RAISERROR 搭配 WITH SETERROR,確保 @@ERROR 可被呼叫端檢測
  • 遠端 RPC 需雙向信任,生產環境建議搭配加密連線與最小權限原則
  • 身為應用開發者,理解資料庫管理觀念 (備份、監控、索引維護) 對效能調校極有幫助
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved