2013-05-01 174 views
0

我在下面的項目上遇到錯誤,我不明白爲什麼。任何人都可以爲我闡述一些啓示嗎?IN子句中的逗號分隔值case case語句錯誤

CREATE FUNCTION dbo.fn_AcMonthOrder 
(
    @Month varchar(100) 
) 
RETURNS INT 
AS 
BEGIN 
    DECLARE @MonthOrder Int 
    SET @MonthOrder = 
     (CASE 
     WHEN @Month IN ('Aug','August',8) THEN 1 
     WHEN @Month IN ('Sep','September',9) THEN 2 
     [email protected] IN ('Oct','October',10) THEN 3 
     ... 
     ELSE 0 END) 
    RETURN @MonthOrder 
END 

如果我試圖調用這個函數,那麼它對一個整數,但對varchars不起作用。即PRINT @ dbo.fn_AcMonthOrder(8)將返回1不如預期,但PRINT @ dbo.fn_AcMonthOrder( '月')或打印@ dbo.fn_AcMonthOrder( '八一')返回以下錯誤:

Msg 245, Level 16, State 1, Line 1 
Conversion failed when converting the varchar value 'Aug' to data type int. 

回答

2

當您在表達式中使用不同的數據類型,SQL Server遵循data type precedence。在這種情況下:

8 IN ('Aug','August', 8) 

你混合intvarchar。由於int具有更高的優先級,因此它會將varchar轉換爲int。這種特殊情況不會引發錯誤的原因可能是優化。這確實引發錯誤:

8 IN ('Aug','August',10) 

而且這並不會引發錯誤:

'Aug' IN ('Aug','August',8) 

但是,這又拋出一個錯誤:

'Sept' IN ('Aug','August',8) 

這證實了優化第一比較不需要轉換的元素。它只在到達不能轉換的元素時纔會引發錯誤。

在一天結束時,最好的解決方案是確保所有數據類型都相同。在你的情況,你可以只列出這些數字作爲一個字符串:

WHEN @Month IN ('Aug','August','8') THEN 1 
           ^^^^^ 
+0

謝謝你標記數據類型的優先順序 - 我設法設置這個,只是通過搞亂 - 但我會在後面深入研究。 – 2013-05-01 07:53:18

1
 WHEN @Month IN ('Aug','August','8') THEN 1 
     WHEN @Month IN ('Sep','September','9') THEN 2 
     [email protected] IN ('Oct','October','10') THEN 3 

用單引號括起數字中的月份值,例如將8更改爲'8'。 這是因爲@Month是VARCHAR()數據類型,而IN()子句要求其中的值必須兼容其中的數據類型轉換。

1

IN列表中的所有元素都必須是可以進行隱式轉換的類型。您不能將varchar值轉換爲整數值,但反之亦然。所以試試這個聲明。

CREATE FUNCTION dbo.fn_AcMonthOrder 
(
    @Month varchar(100) 
) 
RETURNS INT AS 
BEGIN 
    DECLARE @MonthOrder Int 
    SET @MonthOrder = 
    (CASE 
     WHEN @Month IN ('Aug','August','8') THEN 1 
     WHEN @Month IN ('Sep','September','9') THEN 2 
     [email protected] IN ('Oct','October','10') THEN 3 
     ELSE 0 
    END) 
    RETURN @MonthOrder 
END 
+0

謝謝Scoregraphic - 這並修復錯誤,但是我覺得從andomar答案有更多詳細信息(有關數據類型的優先級和優化) – 2013-05-01 07:55:15

1

當您使用IN子句,你應該使用一個數據類型,現在您正在使用「八月」附近,並假定它應該將「月」,......爲int它是不正確。 你可以這樣寫(做它所有你案例Whens)

WHEN @Month IN ('Aug','August','8') THEN 1 
.....