存儲過程是 SQL Server 邏輯封裝、性能優化、安全控制的核心載體。但濫用、寫法不規範會導致維護噩夢。本文從命名、參數、錯誤處理、事務、性能、安全、版本管理七大維度,制定企業級開發規範,附標準模板與代碼審查清單。
| 對象 | 規範 | 示例 |
|---|---|---|
| 存儲過程 | usp_<模塊>_<動作>_<對象>,前綴 usp_ (User Stored Procedure) 區分系統過程 | usp_Order_Create, usp_Report_GetSalesSummary |
| 參數 | @<參數名>,PascalCase,輸入無前綴,輸出加 Out 後綴 | @OrderId, @TotalAmountOut |
| 局部變量 | @<變量名>,camelCase | @rowCount, @tempTable |
| 臨時表 | #tmp_<用途>_<隨機後綴>,避免並發衝突 | #tmp_OrderDetail_ |
CREATE PROCEDURE usp_Module_Action_Object
@InputParam1 INT,
@InputParam2 NVARCHAR(100),
@OutputParam INT OUTPUT,
@ReturnCode INT = 0 OUTPUT -- 統一返回碼:0=成功,>0 業務錯誤碼,<0 系統錯誤碼
AS
BEGIN
SET NOCOUNT ON; -- 禁止返回受影響行數,減少網絡開銷
SET XACT_ABORT ON; -- 運行時錯誤自動回滾事務 (配合 TRY/CATCH)
-- 參數驗證
IF @InputParam1 <= 0
BEGIN
RAISERROR('Invalid InputParam1', 16, 1);
SET @ReturnCode = 1001; RETURN;
END
BEGIN TRY
BEGIN TRANSACTION;
-- 核心業務邏輯
-- ...
COMMIT TRANSACTION;
SET @ReturnCode = 0;
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
-- 錯誤日志寫入 (統一錯誤表)
EXEC usp_Log_Error
@ProcName = OBJECT_NAME(@@PROCID),
@ErrorNumber = ERROR_NUMBER(),
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE(),
@ErrorLine = ERROR_LINE();
SET @ReturnCode = -ERROR_NUMBER(); -- 負數表示系統錯誤
END CATCH
END;
GO
= DEFAULT,避免隱式轉換錯誤。VARCHAR(MAX)/NVARCHAR(MAX)/VARBINARY(MAX) 替代舊 TEXT/NTEXT/IMAGE。CREATE TYPE dbo.OrderDetailType AS TABLE (ProductId INT, Qty INT);OUTPUT 濫用:僅真正需要返回值時使用,多結果集改用 SELECT 返回。1=可提交, -1=不可提交(必須回滾), 0=無事務。@@TRANCOUNT 計數器模式。子過程若開啟事務,外層回滾會回滾所有。建議:僅最外層業務邊界控制事務,內層過程不開啟事務,或檢查 @@TRANCOUNT = 0 才開啟。OPTION (RECOMPILE) (高頻/參數敏感)、OPTIMIZE FOR (@p = typical_value)、局部變量賦值、sp_recompile 定時刷新。sp_executesql @sql, N'@p1 type, @p2 type...', @p1, @p2 參數化,防注入 + 計劃復用。INCLUDE 列消除 Key Lookup,WHERE 條件列前置。EXECUTE 權限,禁止 直接表權限。ADD SIGNATURE TO usp_Proc BY CERTIFICATE CertName,授予證書用戶高權限 (如 VIEW SERVER STATE),過程執行時提權,調用者無需高權限。sp_executesql 參數化,QUOTENAME 包裹標識符。Schema/Module/usp_Proc.sql 組織。INSERT INTO DB_Version (Version, ScriptName, AppliedAt) VALUES (...)。規範的存儲過程是「可讀、可測、可維、可控、安全、高效」六位一體的工程產物。以標準模板為骨架,以代碼審查為護城河,以 SSDT/遷移腳本為交付管道,方能構建穩健可演進的資料庫邏輯層。