2

私はSQLサーバーにこの単純なテーブルを持っています:

DECLARE @tbl table( a int ,  b NVARCHAR(100), isCalcByA bit)

INSERT INTO @tbl
SELECT 1,'c',1
UNION ALL
SELECT 2,'d',0

Ok。

これを実行すると:

SELECT CASE 
            WHEN  isCalcByA = 1 THEN  a
            ELSE  b
       END  FROM @tbl

エラーが発生します:

メッセージ 245、レベル 16、状態 1、行 9
nvarchar 値 'd' をデータ型 int に変換するときに変換に失敗しました。

なぜそれが起こっているのか理解できます:

蓄積中(表示中)のデータは 、intstringを同じ列に並べることができないためです。

Ok

しかし、これはどうですか:

SELECT 'dummy'
FROM   @tbl
WHERE  CASE 
            WHEN isCalcByA = 1 THEN a
            ELSE b
       END IS NOT NULL

ここ -

  • いつも表示していますstring
  • 異なるタイプの異なる表示結果を蓄積しません。
  • または値でnot nullはなく、それらをチェックしています。stringint

しかし、それでも同じエラーが発生します。

何が欠けていますか?

注意

私はこれを行うことができる/行う必要があることを知っています:

SELECT 'dummy'
FROM   @tbl
WHERE 
(isCalcByA = 1 AND a IS NOT NULL)

OR

(isCalcByA <> 1 AND b IS NOT NULL)

(これは正常に動作します)

CASEしかし、最初の状況でなぜ機能しないのか尋ねています

4

4 に答える 4

3

CASE式です -特定の型のを返します。返される可能性のあるすべての値は、すべて共通の型に変換できる必要があります。システムは型の優先順位規則を使用して、考えられるすべての戻り値の型を考慮し、共通の型を決定します。優先順位が高く、勝ちます。int

CASE 
        WHEN isCalcByA = 1 THEN CONVERT(nvarchar(100),a)
        ELSE b
   END

選択された一般的なタイプが明確になったため、機能しnvarchar(100)ます。

于 2013-10-23T08:12:54.733 に答える
1

CASEtheSELECTまたは theWHERE句で使用するかどうかは関係ありません。CASE式は常に同じデータ型を返す必要があります。したがって、両方の列を両方を保持できるデータ型に変換します。

CASE 
    WHEN isCalcByA = 1 THEN CAST(a AS NVARCHAR(100))
    ELSE b
END

CASEのドキュメントから:

result_expressions およびオプションの else_result_expression の型のセットから最も優先度の高い型を返します。

さまざまなパーツWHENELSEパーツのデータ型が結果として異なる場合、このリストから優先順位が最も高いものが選択されます:データ型の優先順位とすべての結果がそのデータ型に変換されます。

intよりも優先順位が高いため、クエリは失敗しnvarcharます。

于 2013-10-23T08:11:30.373 に答える