2012-08-10 56 views
5

我做了SELECT它使用CASE到nvarchar的值轉換成合適的類型,像這樣:話,那麼從句始終評估

SELECT CASE 
    WHEN @propType = 'money' THEN convert(money, datavalue) 
    [...] 
    ELSE datavalue 
END 
FROM [...] 

然而,似乎總是執行convert,即使@propType不是等於錢。可運行的示例:

declare @proptype nvarchar(50)= 'nvarchar' 
declare @val nvarchar(10) = 'test' 
select 
    case @proptype 
     when 'money' then convert(money, @val) 
     else @val 
    end 

爲什麼是這樣的,我該如何解決它? MSDN文檔說明如下:

CASE語句按順序評估其條件,並在條件滿足的第一個條件下停止 。在某些 的情況下,在CASE語句 接收表達式的結果作爲其輸入之前評估表達式。在 評估這些表達式的錯誤是可能的。首先評估 出現在CASE語句的WHEN參數中的聚合表達式,然後提供給CASE語句的 。例如,當生成MAX 聚合的值時,以下查詢 會產生除零錯誤。這發生在評估CASE表達式之前。

我不確定這是否相關,但語言對於非本地語言有些沉重,所以也許它是?

+0

的'varchar'明確地轉換爲'money'時,它的隱含轉換回'varchar'的唯一目的是,據我所知,它們的目的,爲什麼不你要麼把它存儲在所要求的格式開始與或讓客戶端處理格式? – 2012-08-10 09:10:55

+1

源數據不在我的控制之下。在實際情況下,我必須跳過不少箍環才能將數據轉換爲可以插入報表中的格式(這是正確的類型) – carlpett 2012-08-10 09:49:20

回答

3

看一看下面Use caution when Using CONVERT() with CASE or IF functions in Transact SQL (T-SQL)

第一想法通常是下列之一「自評估所述第一 值是數字,它被轉換爲十進制,和所有其他 數據預計也是一個小數「OR」如果SQL Server能夠將任何值轉換爲指定的類型,那麼所有值都是 預期是轉換後的類型「。然而,這是不正確的 (雖然第二個是關閉)!

真正的問題是,如果你選擇在Case語句中的任何位置轉換值 ,數據類型要轉換的值 到是所有值的預期類型,不管它們是 該類型或不。此外,即使NONE值實際上可以被 轉換(即使轉換行代碼從不執行),所有的 值仍然是由 轉換函數指定的類型!

+0

謝謝,這說明了原因,但真的沒有辦法從它前進嗎? – carlpett 2012-08-19 11:12:25

1

要清楚發生了什麼then子句進行評估。

你看到同樣的錯誤,如果你這樣做

SELECT CASE @proptype 
     WHEN 'money' THEN $1.0 /*<-- Literal of datatype money*/ 
     ELSE @val 
     END 

CASE的文檔說明,返回類型

返回從類型集合的優先級最高的類型 result_expressions和可選else_result_expression。有關更多 的信息,請參閱Data Type Precedence (Transact-SQL)

money具有更高的數據類型優先級比nvarchar所以else @val評價那麼被轉換爲money和失敗。

一種可能的解決方法是將其轉換爲sql_variant,因爲它具有比兩者更高的數據優先級。

declare @proptype nvarchar(50)= 'nvarchar' 
declare @val nvarchar(10) = 'test' 
select 
    case @proptype 
     when 'money' then convert(money, @val) 
     else cast(@val as SQL_VARIANT) 
    end