兩個經典 T-SQL 問題:(1) 如何在 SQL 陳述式中取得目前資料庫名稱?(2) 當 GO 批次分隔符切斷變數作用域時,如何跨批次保持計數器?本文提供原生系統函數與游標兩種解法,並說明適用場景。
SELECT DB_NAME() AS CurrentDB; -- 回傳目前連線的資料庫名稱
SELECT DB_NAME(DB_ID()) AS CurrentDB_V2; -- 等效寫法
SELECT DB_NAME() AS CurrentDB; -- 同方法 1
-- 系統檢視替代
SELECT NAME FROM SYS.DATABASES WHERE DATABASE_ID = DB_ID();
EXEC SP_WHO @@SPID; -- 需解析結果集,效能差、權限需求高
結論:直接使用 DB_NAME(),無需查詢系統程序。
背景:GO 為 SSMS/工具的批次分隔符,非 T-SQL 關鍵字。每個批次編譯獨立,區域變數 (@Var) 在批次結束即釋放。
-- 批次 1
CREATE TABLE #LoopState (Counter INT);
INSERT INTO #LoopState VALUES (0);
GO
-- 批次 2 (迴圈主體)
DECLARE @Cnt INT;
SELECT @Cnt = Counter FROM #LoopState;
WHILE @Cnt < 10
BEGIN
-- 業務邏輯:如 ALTER TABLE #Temp ADD Col..., INSERT #Temp...
SET @Cnt = @Cnt + 1;
UPDATE #LoopState SET Counter = @Cnt;
-- 若需再次 GO,此處可結束批次
END
GO
-- 批次 3 讀取最終值
SELECT Counter FROM #LoopState; -- 10
DROP TABLE #LoopState;
-- 建立含計數器的暫存表
CREATE TABLE #Ctrl (ID INT IDENTITY, Cnt INT);
INSERT INTO #Ctrl (Cnt) VALUES (0);
-- 宣告游標
DECLARE Cur CURSOR LOCAL FORWARD_ONLY FOR SELECT Cnt FROM #Ctrl;
OPEN Cur;
FETCH NEXT FROM Cur INTO @Cnt; -- @Cnt 為區域變數,但游標跨批次存活
-- 此處可插入 GO 分隔批次,游標與暫存表不受影響
GO
-- 後續批次繼續使用游標
FETCH NEXT FROM Cur INTO @Cnt;
-- ...
CLOSE Cur; DEALLOCATE Cur;
⚠️ 游標跨 GO 批次在某些工具版本可能失效,暫存表方案更穩健。
:SETVAR LoopMax 10
-- 批次 1
DECLARE @Max INT = $(LoopMax);
-- 批次 2 仍可讀取 $(LoopMax)
GO,避免狀態管理複雜度。DB_NAME()。sqlcmd 變數或 PowerShell 協調。