在 SQL Server 開發中,存儲過程是封裝業務邏輯、提升性能的核心手段。而如何正確獲取存儲過程的返回值,則是每位開發者必須掌握的基本功。本文將系統梳理三種主流返回方式——OUTPUT 參數、RETURN 值、結果集——並配合 T-SQL 與 C# 實戰代碼,助你輕鬆應對各類場景。
OUTPUT 參數是存儲過程對外輸出數據最常用的方式,支持多個輸出參數,類型豐富,適合返回新增記錄的自增 ID、計算結果等。
CREATE PROCEDURE [dbo].[nb_order_insert]
@o_buyerid INT,
@o_id BIGINT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [Order](o_buyerid) VALUES (@o_buyerid);
SET @o_id = @@IDENTITY; -- 將新生成的自增 ID 回傳
END
調用示例:
DECLARE @o_buyerid INT = 1001;
DECLARE @o_id BIGINT;
EXEC [nb_order_insert] @o_buyerid, @o_id OUTPUT;
SELECT @o_id AS NewOrderId; -- 獲得剛插入訂單的 ID
public static decimal GetUserAmount(int uid)
{
decimal amount = 0;
using (var conn = new SqlConnection(ConnStr))
using (var cmd = new SqlCommand("Cart_UserAmount", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@UID", uid);
// 關鍵:Direction = ParameterDirection.Output
cmd.Parameters.Add("@Amount", SqlDbType.Decimal).Direction = ParameterDirection.Output;
conn.Open();
cmd.ExecuteNonQuery();
amount = (decimal)cmd.Parameters["@Amount"].Value;
}
return amount;
}
RETURN 只能返回 INT 類型,通常用於表示執行狀態(如 0 失敗、1 成功)或影響行數。注意:RETURN 會立即結束存儲過程。
CREATE PROCEDURE [dbo].[nb_order_insert]
@o_buyerid INT,
@o_id BIGINT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (SELECT 1 FROM [Shop] WHERE [s_id] = @o_buyerid)
BEGIN
INSERT INTO [Order](o_buyerid) VALUES (@o_buyerid);
SET @o_id = @@IDENTITY;
RETURN 1; -- 成功
END
ELSE
BEGIN
RETURN 0; -- 失敗:買家不存在
END
END
調用示例:
DECLARE @o_buyerid INT = 1001;
DECLARE @o_id BIGINT;
DECLARE @result INT;
EXEC @result = [nb_order_insert] @o_buyerid, @o_id OUTPUT;
SELECT @result AS RetCode; -- 1 或 0
public static int AddUser(User us)
{
int retVal = -1;
using (var conn = new SqlConnection(ConnStr))
using (var cmd = new SqlCommand("User_Add", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
// 輸入參數
cmd.Parameters.AddWithValue("@UName", us.UName);
cmd.Parameters.AddWithValue("@UPass", us.UPass);
// ... 其他參數省略 ...
// 關鍵:Direction = ParameterDirection.ReturnValue
cmd.Parameters.Add("@RETURN_VALUE", SqlDbType.Int).Direction = ParameterDirection.ReturnValue;
conn.Open();
cmd.ExecuteNonQuery();
retVal = (int)cmd.Parameters["@RETURN_VALUE"].Value;
}
return retVal;
}
存儲過程中直接 SELECT 即可返回結果集,適合分頁、報表、列表頁等場景。
CREATE PROCEDURE [dbo].[nb_order_select]
@o_id INT
AS
BEGIN
SET NOCOUNT ON;
SELECT o_id, o_buyerid FROM [Order] WHERE o_id = @o_id;
END
若需在 T-SQL 中進一步處理結果集,可用 INSERT ... EXEC 配合臨時表:
CREATE TABLE #Temp (
o_id BIGINT IDENTITY(1,1) NOT NULL,
o_buyerid INT NOT NULL
);
INSERT #Temp EXEC [nb_order_select] @o_id = 1001;
SELECT * FROM #Temp;
DROP TABLE #Temp;
public static DataSet ExecuteSpReturnDataSet(string spName, params SqlParameter[] parameters)
{
using (var conn = new SqlConnection(ConnStr))
using (var cmd = new SqlCommand(spName, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
if (parameters != null) cmd.Parameters.AddRange(parameters);
var da = new SqlDataAdapter(cmd);
var ds = new DataSet();
da.Fill(ds);
return ds;
}
}
// 調用
var ds = ExecuteSpReturnDataSet("nb_order_select", new SqlParameter("@o_id", 1001));
var dt = ds.Tables[0]; // 獲得 DataTable
| 特性 | OUTPUT 參數 | RETURN 值 | 結果集 |
|---|---|---|---|
| 返回數量 | 多個 | 單個 | 多行多列 |
| 數據類型 | 任意標量類型 | 僅 INT | 任意 |
| 適用場景 | 新增 ID、計算值、多值輸出 | 狀態碼、影響行數 | 查詢列表、報表數據 |
| C# 接收方式 | ParameterDirection.Output | ParameterDirection.ReturnValue | SqlDataAdapter.Fill / ExecuteReader |
掌握三種返回方式的優劣與適用場景,能讓你的存儲過程設計更專業、調用更高效、維護更輕鬆。實戰中建議結合 OUTPUT + 結果集 的組合:寫操作用 OUTPUT 回傳關鍵標識,讀操作直接返回結果集,RETURN 僅作為執行狀態的「紅綠燈」。