理解順序是寫出高性能查詢的前提:
FROM / JOIN → 產生虛擬表 VT1(笛卡爾積)ON → 篩選 VT1 → VT2OUTER JOIN → 添加外部行 → VT3WHERE → 篩選 VT3 → VT4GROUP BY → 分組 VT4 → VT5CUBE | ROLLUP → 超組 → VT6HAVING → 篩選組 → VT7SELECT → 選列 → VT8DISTINCT → 去重 → VT9ORDER BY → 排序 → VC10(游標)TOP / OFFSET-FETCH → 取子集 → VT11(最終結果)核心啟示:SELECT 列表最後執行,別名不可在 WHERE/GROUP BY/HAVING 中使用;FROM 最先執行,駕駛表選擇關鍵。
CREATE PROCEDURE [dbo].[usp_BusinessAction]
@Param1 INT,
@Param2 NVARCHAR(100)
AS
BEGIN
SET NOCOUNT ON; -- 關閉 DONE_IN_PROC 消息,提升性能
SET XACT_ABORT ON; -- 運行時錯誤自動回滾事務
DECLARE @StartTime DATETIME2 = SYSDATETIME(); -- 統一時間基準
BEGIN TRY
BEGIN TRANSACTION;
-- === 核心業務邏輯 ===
-- INSERT/UPDATE/DELETE ...
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
DECLARE @ErrMsg NVARCHAR(4000) = ERROR_MESSAGE(),
@ErrSev INT = ERROR_SEVERITY(),
@ErrState INT = ERROR_STATE();
RAISERROR(@ErrMsg, @ErrSev, @ErrState); -- 重拋異常給調用方
RETURN -1;
END CATCH
END;
同上,但在 TRY 塊中顯式管理 BEGIN/COMMIT/ROLLBACK TRANSACTION,適用於多語句必須原子提交的場景。
SELECT *
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY ProductNO ORDER BY CreateDate DESC) AS rn, *
FROM dbo.ItemInfo
) t
WHERE rn <= 3; -- 每組前 3 條
CREATE TYPE [dbo].[GiftCardBatch] AS TABLE (
RowNum INT NULL,
GiftCardNO VARCHAR(500) NULL,
UsedDate DATETIME NULL,
CustomerName VARCHAR(50) NULL,
ReduceAmount DECIMAL(18,2) NULL,
Amount DECIMAL(18,2) NULL
);
// C# 偽碼
var dt = new DataTable();
dt.Columns.Add("RowNum", typeof(int));
dt.Columns.Add("GiftCardNO", typeof(string));
// ... 填充行
using (var cmd = new SqlCommand("usp_ProcessGiftCards", conn) { CommandType = CommandType.StoredProcedure })
{
var p = cmd.Parameters.AddWithValue("@Batch", dt);
p.SqlDbType = SqlDbType.Structured;
p.TypeName = "dbo.GiftCardBatch";
cmd.ExecuteNonQuery();
}
CREATE PROCEDURE usp_ProcessGiftCards
@Batch GiftCardBatch READONLY -- 必須 READONLY
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.GiftCardLog (CardNO, Customer, Amount, UsedDate)
SELECT GiftCardNO, CustomerName, Amount, UsedDate
FROM @Batch;
END;
| 需求 | 代碼/技巧 |
|---|---|
| 獲取所有用戶表 | SELECT name FROM sys.objects WHERE type='U' AND is_ms_shipped=0 |
| 獲取表所有列 | SELECT name FROM sys.columns WHERE object_id=OBJECT_ID('table') |
| 搜索引用某表的對象 | SELECT o.* FROM sys.objects o JOIN syscomments c ON o.id=c.id WHERE c.text LIKE '%table_name%' |
| 修改數據庫名稱 | ALTER DATABASE [old] MODIFY NAME = [new]; (或 sp_renamedb) |
| 殺掉所有 Profiler 進程 | DECLARE c CURSOR FOR SELECT 'KILL '+spid FROM sys.sysprocesses WHERE program_name LIKE '%Profiler%'; OPEN c; FETCH NEXT FROM c INTO @sql; WHILE @@FETCH_STATUS=0 BEGIN EXEC(@sql); FETCH NEXT FROM c INTO @sql; END |
| 按筆畫排序 | ORDER BY Name COLLATE Chinese_PRC_Stroke_CI_AS |
| 密碼加密/比較 | PWDENCRYPT('pwd') / PWDCOMPARE('pwd', hash) |