核心優勢:執行效能優於動態 SQL。預存程序經預編譯、計畫快取重用,減少剖析與最佳化開銷;網路傳輸量較小(僅傳呼叫指令);可封裝商業邏輯,減少應用層程式碼。
將多條 SQL 陳述式封裝為單一單元,支援條件判斷、流程控制、參數傳遞、錯誤處理,實現模組化與重用。
CREATE PROCEDURE dbo.GetUsersDesc
AS
SELECT UserID FROM Users ORDER BY UserID DESC;
註:名稱避開保留字即可,AS 以下為程式本體。
public static string GetCustomerCName(ref ArrayList arrayCName, ref ArrayList arrayID)
{
using (SqlConnection con = ADConnection.createConnection())
using (SqlCommand cmd = new SqlCommand("GetUsersDesc", con))
{
cmd.CommandType = CommandType.StoredProcedure;
con.Open();
try
{
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
if (!string.IsNullOrEmpty(dr[0].ToString()))
{
arrayCName.Add(dr[1].ToString());
}
}
}
return "OK!";
}
catch (Exception ex)
{
return ex.ToString();
}
}
}
改進重點:採用 using 確保連線釋放;參數化查詢防注入;CommandType.StoredProcedure 明確指定類型。
| 維度 | 預存程序 | 動態 SQL |
|---|---|---|
| 執行效能 | 計畫快取重用、預編譯優勢 | 每次剖析編譯,計畫難重用 |
| 安全性 | 權限管控於程序層級,防 SQL Injection | 字串串接易產生注入風險 |
| 維護性 | 集中管理、版本控管、獨立部署 | 散落應用程式碼,難追蹤 |
| 除錯與分析 | Profiler / Extended Events 易追蹤 | SQL 文本分散,分析困難 |
| 網路流量 | 僅傳呼叫指令與參數 | 完整 SQL 文本傳輸 |
| 彈性 | 結構固定,動態結構需動態 SQL | 極高彈性,支援動態欄位/表/條件 |
usp_<模組>_<動作>(如 usp_Order_GetByCustomer)預存程序非銀彈,但在企業級應用中,其效能、安全、維護三大優勢使其成為核心資料存取層的首選。搭配參數化動態 SQL 於適當場景,構建兼具效能與彈性的資料存取架構。