共用方式為


案例 (Transact-SQL)

適用於:SQL ServerAzure SQL 資料庫Azure SQL 受控執行個體Azure Synapse Analytics分析平台系統(PDW)Microsoft Fabric 中的 SQL 分析端點Microsoft Fabric 中的倉儲Microsoft Fabric 中的 SQL 資料庫

評估一份條件清單,並傳回多個可能的結果運算式之一。

CASE 運算式有兩種格式:

  • 簡單CASE運算式會將運算式與一組簡單運算式進行比較,以決定結果。

  • 搜尋的CASE運算式會評估一組布林運算式,以判斷結果。

這兩種格式都支援選擇性 ELSE 引數。

CASE 可以用在允許有效運算式的任何陳述式或子句中。 例如,您可以使用 CASE in 陳述式 (例如 SELECTUPDATEDELETESET ,) 和 in 子句 (例如 <select_list>INWHEREORDER BYHAVING和 )。

Transact-SQL 語法慣例

Syntax

SQL Server、Azure SQL 資料庫和 Azure Synapse Analytics 的語法。

-- Simple CASE expression:
CASE input_expression
     WHEN when_expression THEN result_expression [ ...n ]
     [ ELSE else_result_expression ]
END

-- Searched CASE expression:
CASE
     WHEN Boolean_expression THEN result_expression [ ...n ]
     [ ELSE else_result_expression ]
END

平行處理資料倉儲的語法。

CASE
     WHEN when_expression THEN result_expression [ ...n ]
     [ ELSE else_result_expression ]
END

Arguments

input_expression

這是使用簡單的 CASE 格式時,所評估的運算式。 input_expression 是任何有效的運算式

什麼時候 when_expression

這是使用簡單的 格式時,要與 CASE 進行比較的簡單運算式。 when_expression 是任何有效的運算式。 input_expression 和每個 when_expression 的資料類型都必須相同,或必須能夠進行隱含轉換。

然後 result_expression

input_expression 等於 when_expression 評估 TRUE為 時傳回的運算式,或 Boolean_expression 評估為 TRUEresult expression 是任何有效的運算式

否則 else_result_expression

如果沒有比較作業評估為 TRUE,則傳回的運算式。 如果省略此引數,且沒有比較作業評估為 TRUECASE 則會傳回 NULLelse_result_expression 是任何有效的運算式。 else_result_expression 和任何 result_expression 的資料類型都必須相同,或必須能夠進行隱含轉換。

什麼時候 Boolean_expression

這是使用搜尋的 CASE 格式時,所評估的布林運算式。 Boolean_expression 是任何有效的布林值運算式。

傳回類型

result_expressions 和選擇性 else_result_expression 的類型集傳回優先順序最高的類型。 如需詳細資訊,請參閱 數據類型優先順序

傳回值

簡單的 CASE 運算式

簡單 CASE 表達式的運作方式是將第一個表達式與每個 WHEN 子句中的表達式進行比較,以實現對等性。 如果這些運算式相等,則會傳回子句中的 THEN 運算式。

  • 僅允許相等檢查。

  • 依指定的順序,評估每個 WHEN 子句的 input_expression = when_expression。

  • 傳回第一個input_expression = 的result_expression,其評估值為 TRUE

  • 如果沒有input_expression = when_expression評估為 TRUE,如果指定子句,SQL ELSE Server 資料庫引擎會傳回NULL,如果未指定子ELSE句,則傳回值。

搜尋的 CASE 運算式

  • 依指定的順序評估每個子句的WHEN

  • 傳回第一個評估為 的Boolean_expressionTRUE

  • 如果沒有Boolean_expression評估TRUE為 ,如果指定子句,資料庫ELSE引擎會傳回NULL,如果未指定子ELSE句,則會傳回值。

Remarks

SQL Server 在 CASE 運算式中只允許 10 層的巢狀層級。

CASE 運算式無法用於控制 Transact-SQL 陳述式、陳述式區塊、使用者定義函數及預存程序的執行流程。 如需流程控制方法的清單,請參閱 流程控制

CASE 運算式會依序評估其條件,並在滿足其條件的第一個條件時停止。 在某些情況下,運算式會先進行評估,CASE 運算式才會收到該運算式的結果作為其輸入。 評估這些運算式是否可能時發生錯誤。 首先評估出現在運算式引WHEN數中的CASE聚集運算式,然後提供給CASE運算式。 例如,下列查詢在產生彙總值 MAX 時會產生除以零錯誤。 此步驟會在評估 CASE 運算式之前發生。

WITH Data (value)
AS (
    SELECT 0
    UNION ALL
    SELECT 1
    )
SELECT CASE
        WHEN MIN(value) <= 0 THEN 0
        WHEN MAX(1 / value) >= 100 THEN 1
        END
FROM Data;
GO

您應該只依賴純量運算式 (包括傳回純量的非相關子查詢) 條件的 WHEN 評估順序,而不是彙總運算式。

您也必須確定 or THENELSE 子句中至少有一個運算式不是 NULL 常數。 雖然可以從多個結果表達式傳回,但 NULL 並非所有結果表達式都可以明確地成為 NULL 常數。 如果所有結果運算式都使用 NULL 常數,則會傳回錯誤 8133。

Examples

本文中的程式代碼範例會使用 AdventureWorks2025AdventureWorksDW2025 範例資料庫,您可以從 Microsoft SQL Server 範例和社群專案 首頁下載。

A. 使用 SELECT 陳述式搭配簡單的 CASE 運算式

SELECT 陳述式內,只允許相等檢查使用簡單的 CASE 運算式,不能進行任何其他比較。 下列範例利用 CASE 運算式來變更產品線類別目錄的顯示方式,使它們更容易了解。

USE AdventureWorks2022;
GO

SELECT ProductNumber,
    Category = CASE ProductLine
        WHEN 'R' THEN 'Road'
        WHEN 'M' THEN 'Mountain'
        WHEN 'T' THEN 'Touring'
        WHEN 'S' THEN 'Other sale items'
        ELSE 'Not for sale'
        END,
    Name
FROM Production.Product
ORDER BY ProductNumber;
GO

B. 使用 SELECT 陳述式搭配搜尋的 CASE 運算式

SELECT 陳述式內,搜尋的 CASE 運算式允許以比較值為基礎來取代結果集中的值。 下列範例以產品的價格範圍為基礎,將標價顯示為文字註解。

USE AdventureWorks2022;
GO

SELECT ProductNumber,
    Name,
    "Price Range" = CASE
        WHEN ListPrice = 0 THEN 'Mfg item - not for resale'
        WHEN ListPrice < 50 THEN 'Under $50'
        WHEN ListPrice >= 50 AND ListPrice < 250 THEN 'Under $250'
        WHEN ListPrice >= 250 AND ListPrice < 1000 THEN 'Under $1000'
        ELSE 'Over $1000'
        END
FROM Production.Product
ORDER BY ProductNumber;
GO

C. 在 ORDER BY 子句中使用 CASE

下列範例會使用 CASE 子句中的 ORDER BY 運算式,根據指定的資料行值來決定資料列的排序順序。 在第一則範例中,系統會評估 SalariedFlag 資料表之 HumanResources.Employee 資料行的值。 將 SalariedFlag 設定為 1 的員工會以 BusinessEntityID 的遞減順序傳回。 將 SalariedFlag 設定為 0 的員工會以 BusinessEntityID 的遞增順序傳回。

SELECT BusinessEntityID,
    SalariedFlag
FROM HumanResources.Employee
ORDER BY CASE SalariedFlag
        WHEN 1 THEN BusinessEntityID
        END DESC,
    CASE
        WHEN SalariedFlag = 0 THEN BusinessEntityID
        END;
GO

在第二則範例中,結果集會依照資料行 TerritoryName 排序 (當資料行 CountryRegionName 等於 'United States' 時) 以及依照 CountryRegionName 排序 (針對所有其他資料列)。

SELECT BusinessEntityID,
    LastName,
    TerritoryName,
    CountryRegionName
FROM Sales.vSalesPerson
WHERE TerritoryName IS NOT NULL
ORDER BY CASE CountryRegionName
        WHEN 'United States' THEN TerritoryName
        ELSE CountryRegionName
        END;
GO

D. 在 UPDATE 陳述式中使用 CASE

下列範例使用CASE陳述式中的UPDATE表示式來決定為 0 的VacationHours員工直欄SalariedFlag設定的值。 從 VacationHours 減去 10 小時變成負值時,VacationHours 會加上 40 小時,否則 VacationHours 會加上 20 小時。 子 OUTPUT 句用來顯示休假前後值。

USE AdventureWorks2022;
GO

UPDATE HumanResources.Employee
SET VacationHours = (
        CASE
            WHEN ((VacationHours - 10.00) < 0) THEN VacationHours + 40
            ELSE (VacationHours + 20.00)
            END
        )
OUTPUT Deleted.BusinessEntityID,
    Deleted.VacationHours AS BeforeValue,
    Inserted.VacationHours AS AfterValue
WHERE SalariedFlag = 0;
GO

E. 在 SET 陳述式中使用 CASE

下列範例在表格值函數CASE的陳述式中使用SETdbo.GetContactInfo運算式。 在 AdventureWorks2025 資料庫中,與人員相關的所有資料都會儲存在 Person.Person 資料表中。 例如,此人可能是員工、廠商代表或客戶。 此函數會傳回指定FirstName人員的名字 (LastName) 和姓氏 (BusinessEntityID) 以及該人員的連絡人類型。 CASE陳述式中的SET運算式會根據 、 ContactTypeBusinessEntityID表格中EmployeeVendor欄的存在,決定要顯示直欄Customer的值。

USE AdventureWorks2022;
GO

CREATE FUNCTION dbo.GetContactInformation (
    @BusinessEntityID INT
)
RETURNS
    @retContactInformation TABLE (
        BusinessEntityID INT NOT NULL,
        FirstName NVARCHAR (50) NULL,
        LastName NVARCHAR (50) NULL,
        ContactType NVARCHAR (50) NULL,
        PRIMARY KEY CLUSTERED (BusinessEntityID ASC))
AS
-- Returns the first name, last name and contact type for the specified contact.
BEGIN
    DECLARE @FirstName NVARCHAR(50),
        @LastName NVARCHAR(50),
        @ContactType NVARCHAR(50);

    -- Get common contact information
    SELECT @BusinessEntityID = BusinessEntityID,
        @FirstName = FirstName,
        @LastName = LastName
    FROM Person.Person
    WHERE BusinessEntityID = @BusinessEntityID;

    SET @ContactType = CASE
            -- Check for employee
            WHEN EXISTS (
                    SELECT *
                    FROM HumanResources.Employee AS e
                    WHERE e.BusinessEntityID = @BusinessEntityID
                    )
                THEN 'Employee'
            -- Check for vendor
            WHEN EXISTS (
                    SELECT *
                    FROM Person.BusinessEntityContact AS bec
                    WHERE bec.BusinessEntityID = @BusinessEntityID
                    )
                THEN 'Vendor'
            -- Check for store
            WHEN EXISTS (
                    SELECT *
                    FROM Purchasing.Vendor AS v
                    WHERE v.BusinessEntityID = @BusinessEntityID
                    )
                THEN 'Store Contact'
            -- Check for individual consumer
            WHEN EXISTS (
                    SELECT *
                    FROM Sales.Customer AS c
                    WHERE c.PersonID = @BusinessEntityID
                    )
                THEN 'Consumer'
            END;

    -- Return the information to the caller
    IF @BusinessEntityID IS NOT NULL
        BEGIN
            INSERT @retContactInformation
            SELECT @BusinessEntityID,
                   @FirstName,
                   @LastName,
                   @ContactType;
        END
    RETURN;
END
GO

SELECT BusinessEntityID,
    FirstName,
    LastName,
    ContactType
FROM dbo.GetContactInformation(2200);
GO

SELECT BusinessEntityID,
    FirstName,
    LastName,
    ContactType
FROM dbo.GetContactInformation(5);
GO

F. 在 HAVING 子句中使用 CASE

下列範例會使用 CASE 子句中的 HAVING 運算式來限制陳述式所 SELECT 傳回的資料列。 此陳述式會傳回 HumanResources.Employee 資料表中每個職稱的時薪。 該 HAVING 條款將頭銜限制為最高工資率大於 40 美元的受薪員工或最高工資率大於 15 美元的非工資員工所持有的頭銜。

USE AdventureWorks2022;
GO

SELECT JobTitle,
    MAX(ph1.Rate) AS MaximumRate
FROM HumanResources.Employee AS e
INNER JOIN HumanResources.EmployeePayHistory AS ph1
    ON e.BusinessEntityID = ph1.BusinessEntityID
GROUP BY JobTitle
HAVING (
    MAX(CASE
            WHEN SalariedFlag = 1 THEN ph1.Rate
            ELSE NULL
        END) > 40.00
    OR MAX(CASE
            WHEN SalariedFlag = 0 THEN ph1.Rate
            ELSE NULL
        END) > 15.00
)
ORDER BY MaximumRate DESC;
GO

G. 使用巢狀 CASE 運算式來分類結果

下列範例使用巢狀 CASE 運算式,根據 對產品 ListPrice進行分類。 如果產品標價超過 1,000 美元,則會將其視為 High-end。 其餘產品會根據 和 CASE分類ProductLine在巢狀ListPrice運算式中。

USE AdventureWorks2022;
GO

SELECT 
    ProductNumber,
    Name,
    ListPrice,
    PriceCategory = 
        CASE 
            WHEN ListPrice > 1000 THEN 'High-end'
            ELSE 
                CASE ProductLine
                    WHEN 'R' THEN
                        CASE 
                            WHEN ListPrice > 500 THEN 'Premium Road'
                            ELSE 'Standard Road'
                        END
                    WHEN 'M' THEN
                        CASE 
                            WHEN ListPrice > 500 THEN 'Premium Mountain'
                            ELSE 'Standard Mountain'
                        END
                    WHEN 'T' THEN 'Touring'
                    ELSE 'Other'
                END
        END
FROM Production.Product
ORDER BY ListPrice DESC;

範例:Azure Synapse Analytics 和 Analytics Platform System (PDW)

H. 使用 SELECT 陳述式搭配 CASE 運算式

在陳述式內 SELECTCASE 運算式容許根據比較值取代結果集中的值。 下列範例利用 CASE 運算式來變更產品線類別目錄的顯示方式,使它們更容易了解。 當值不存在時,會顯示文字 Not for sale

SELECT ProductAlternateKey,
    Category = CASE ProductLine
        WHEN 'R' THEN 'Road'
        WHEN 'M' THEN 'Mountain'
        WHEN 'T' THEN 'Touring'
        WHEN 'S' THEN 'Other sale items'
        ELSE 'Not for sale'
        END,
    EnglishProductName
FROM dbo.DimProduct
ORDER BY ProductKey;
GO

I. 在 UPDATE 陳述式中使用 CASE

下列範例使用CASE陳述式中的UPDATE表示式來決定為 0 的VacationHours員工直欄SalariedFlag設定的值。 從 VacationHours 減去 10 小時變成負值時,VacationHours 會加上 40 小時,否則 VacationHours 會加上 20 小時。

UPDATE dbo.DimEmployee
SET VacationHours = (
        CASE
            WHEN ((VacationHours - 10.00) < 0) THEN VacationHours + 40
            ELSE (VacationHours + 20.00)
            END
        )
WHERE SalariedFlag = 0;
GO