將常用或復雜的 SQL 邏輯預編譯存儲在數據庫中,賦予一個名稱,調用時僅需 EXEC 過程名 即可自動執行。
| 維度 | 普通 SQL | 存儲過程 |
|---|---|---|
| 編譯 | 每次執行編譯一次 | 創建時編譯,後續復用計劃 |
| 網絡傳輸 | 發送完整 SQL 文本 | 僅發送調用命令 |
| 事務封裝 | 客戶端控制 | 服務端原子性封裝 |
| 復用性 | 低 | 高(模塊化) |
| 安全性 | 需表級權限 | 僅授 EXEC 權限,隱藏表結構 |
sp_ 前綴,管理/信息查詢(如 sp_help)xp_ 前綴,調用 OS 功能(如 xp_cmdshell)CREATE PROCEDURE 過程名
@參數名 數據類型 [OUTPUT],
...
[WITH {RECOMPILE | ENCRYPTION}]
AS
BEGIN
-- SQL 語句
END;
OUTPUT:標記輸出參數WITH RECOMPILE:每次執行重新編譯(應對參數嗅探)WITH ENCRYPTION:加密定義文本(sp_helptext 不可見)CREATE PROC upGetUserName
@intUserId INT,
@ostrUserName NVARCHAR(20) OUTPUT
AS
BEGIN
SELECT @ostrUserName = uName FROM uUser WHERE uId = @intUserId;
END;
SET ANSI_NULLS ON; GO
SET QUOTED_IDENTIFIER ON; GO
CREATE PROCEDURE sp_test
@id INT,
@name VARCHAR(20) OUTPUT
AS
BEGIN
SET NOCOUNT ON; -- 關鍵:抑制 DONE_IN_PROC 消息,提升性能
SELECT @name = name FROM test WHERE id = @id;
END;
GO
-- SSMS / sqlcmd
DECLARE @return_value INT, @name VARCHAR(20);
EXEC @return_value = dbo.sp_test @id = 1, @name = @name OUTPUT;
SELECT @name AS '@name';
SELECT 'Return Value' = @return_value;
SqlCommand cmd = new SqlCommand("sp_test", conn) { CommandType = CommandType.StoredProcedure }; cmd.Parameters.Add("@id", SqlDbType.Int).Value = 1; var p = cmd.Parameters.Add("@name", SqlDbType.VarChar, 20); p.Direction = ParameterDirection.Output; cmd.ExecuteNonQuery(); string name = p.Value.ToString();CallableStatement cs = conn.prepareCall("{? = call sp_test(?, ?)}"); cs.registerOutParameter(1, Types.INTEGER); cs.setInt(2, 1); cs.registerOutParameter(3, Types.VARCHAR); cs.execute();@ 開頭OUTPUT 參數調用端必須註冊方向RETURN 強退(用 THROW 或 RAISERROR)SET NOCOUNT ONWITH RECOMPILEsp_helptext 查看,備份腳本