首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

T-SQL 流程控制語句完整指南:IF/CASE/WHILE/BEGIN...END

     編輯:關於SqlServer

Transact-SQL 程式流程控制核心語法

T-SQL 提供完整的程式流程控制能力,支援條件判斷、迴圈、區塊結構,是撰寫預存程序、觸發器、批次腳本的基礎。

1. IF...ELSE 條件判斷

-- 基本語法
IF <條件運算式>
    <陳述式或區塊>
[ELSE
    <陳述式或區塊>]

-- 範例:薪資等級判斷
DECLARE @Salary MONEY = 55000;

IF @Salary > 50000
    PRINT '高薪資等級';
ELSE IF @Salary > 30000
    PRINT '中薪資等級';
ELSE
    PRINT '初級薪資等級';

關鍵規則

  • 條件運算式必須回傳布林值 (TRUE/FALSE/UNKNOWN)
  • 單一陳述式可省略 BEGIN...END,多行必須使用區塊
  • 巢狀深度限制 32 層
  • ELSE 綁定最近的未配對 IF

實戰範例:動態 SQL 條件建構

CREATE PROCEDURE dbo.usp_GetOrders
    @CustomerID NCHAR(5) = NULL,
    @OrderDateFrom DATE = NULL,
    @OrderDateTo DATE = NULL
AS
BEGIN
    DECLARE @SQL NVARCHAR(MAX) = N'SELECT * FROM dbo.Orders WHERE 1=1';
    
    IF @CustomerID IS NOT NULL
        SET @SQL += N' AND CustomerID = @CustID';
    
    IF @OrderDateFrom IS NOT NULL
        SET @SQL += N' AND OrderDate >= @DateFrom';
    
    IF @OrderDateTo IS NOT NULL
        SET @SQL += N' AND OrderDate <= @DateTo';
    
    EXEC sp_executesql @SQL,
        N'@CustID NCHAR(5), @DateFrom DATE, @DateTo DATE',
        @CustID = @CustomerID, @DateFrom = @OrderDateFrom, @DateTo = @OrderDateTo;
END;

2. BEGIN...END 區塊結構

BEGIN
    -- 區域變數宣告 (僅在區塊內有效)
    DECLARE @LocalVar INT = 10;
    
    -- 多行陳述式
    SET @LocalVar = @LocalVar * 2;
    PRINT @LocalVar;
    
    -- 巢狀區塊
    BEGIN
        DECLARE @InnerVar INT = 5;
        PRINT @InnerVar;
    END
    -- @InnerVar 在此處不可見
END

使用時機

  • IF/ELSE/WHILE 多行陳述式
  • 交易控制區塊 (BEGIN TRAN...COMMIT/ROLLBACK)
  • 錯誤處理區塊 (BEGIN TRY...END TRY BEGIN CATCH...END CATCH)
  • 限制變數作用域

3. CASE 運算式 (兩種形式)

簡單 CASE 運算式 (等值比較)

CASE <輸入運算式>
    WHEN <比較值1> THEN <結果1>
    WHEN <比較值2> THEN <結果2>
    ...
    [ELSE <預設結果>]
END

-- 範例:州代碼轉全名
SELECT 
    State,
    CASE State
        WHEN 'CA' THEN 'California'
        WHEN 'NY' THEN 'New York'
        WHEN 'TX' THEN 'Texas'
        ELSE 'Other State'
    END AS StateName
FROM Customers;

搜尋 CASE 運算式 (布林運算式)

CASE
    WHEN <布林運算式1> THEN <結果1>
    WHEN <布林運算式2> THEN <結果2>
    ...
    [ELSE <預設結果>]
END

-- 範例:薪資區間分級
SELECT 
    EmployeeName,
    Salary,
    CASE
        WHEN Salary >= 100000 THEN 'Executive'
        WHEN Salary >= 70000 THEN 'Senior'
        WHEN Salary >= 40000 THEN 'Mid-Level'
        ELSE 'Junior'
    END AS Level
FROM Employees;

CASE 進階應用

  • 彙總條件計數:SUM(CASE WHEN Status = 'Active' THEN 1 ELSE 0 END)
  • 動態排序:ORDER BY CASE @SortCol WHEN 'Name' THEN Name WHEN 'Date' THEN HireDate END
  • 避免除零錯誤:CASE WHEN Divisor = 0 THEN NULL ELSE Dividend / Divisor END
  • PIVOT 替代:條件彙總產生交叉表

4. WHILE 迴圈控制

WHILE <布林條件>
BEGIN
    <陳述式區塊>
    [BREAK;]      -- 立即跳出迴圈
    [CONTINUE;]   -- 跳過本次剩餘陳述式,進入下一次迭代
END

基本範例:遞迴階乘計算

DECLARE @N INT = 5, @Factorial BIGINT = 1, @Counter INT = 1;

WHILE @Counter <= @N
BEGIN
    SET @Factorial = @Factorial * @Counter;
    SET @Counter += 1;
    
    -- 提前結束示範
    IF @Factorial > 100
        BREAK;
END
PRINT @Factorial; -- 120

巢狀迴圈與 BREAK/CONTINUE 行為

DECLARE @i INT = 1, @j INT;

WHILE @i <= 3
BEGIN
    SET @j = 1;
    WHILE @j <= 3
    BEGIN
        IF @i = 2 AND @j = 2
            BREAK;  -- 只跳出內層迴圈,外層繼續
        
        PRINT CONCAT('i=', @i, ' j=', @j);
        SET @j += 1;
    END
    SET @i += 1;
END
-- 輸出: i=1 j=1, i=1 j=2, i=1 j=3, i=2 j=1, i=3 j=1, i=3 j=2, i=3 j=3

游標搭配 WHILE 迴圈 (經典模式)

DECLARE @Name NVARCHAR(100);
DECLARE cur CURSOR LOCAL FAST_FORWARD FOR
    SELECT Name FROM dbo.Products WHERE Price > 100;

OPEN cur;
FETCH NEXT FROM cur INTO @Name;

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT @Name;
    FETCH NEXT FROM cur INTO @Name;
END

CLOSE cur;
DEALLOCATE cur;

5. 進階流程控制技巧

GOTO 標籤跳轉 (慎用)

DECLARE @Counter INT = 0;
StartLoop:
SET @Counter += 1;
PRINT @Counter;
IF @Counter < 5 GOTO StartLoop;
-- 輸出 1 到 5

RETURN 結束批次/程序

CREATE PROCEDURE dbo.usp_ValidateOrder @OrderID INT
AS
BEGIN
    IF NOT EXISTS (SELECT 1 FROM Orders WHERE OrderID = @OrderID)
    BEGIN
        RAISERROR('訂單不存在', 16, 1);
        RETURN -1;  -- 立即結束程序,回傳狀態碼
    END
    -- 後續邏輯...
    RETURN 0;
END;

THROW 重新拋出例外 (2012+)

BEGIN TRY
    -- 可能失敗的操作
    INSERT INTO Orders ...;
END TRY
BEGIN CATCH
    -- 記錄錯誤
    INSERT INTO ErrorLog ...;
    -- 重新拋出原始例外
    THROW;
END CATCH;

效能與最佳實踐總結

建議說明
避免游標,改用集合操作SET-based 操作通常比逐列處理快 10-100 倍
WHILE 迴圈內避免 SELECT * FROM 大表改用索引查詢、暫存表、表變數減少 I/O
CASE 運算式優於多個 IF/ELSE查詢最佳化器可產生更有效執行計畫
使用 sp_executesql 替代 EXEC(@sql)參數化、計畫重用、防注入
BEGIN TRY/CATCH 取代 @@ERROR 檢查結構化錯誤處理、支援嵌套、THROW 保留堆疊
變數宣告盡量靠近使用位置減少作用域、提高可讀性、避免重複宣告錯誤
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved