2011-02-03 3 views
5

でCASTを使用しているとき、私は私がやろうとしていますどのような次データ変換エラーCASE文

 declare 
    @completeCommand  nvarchar (max) = 'x' 
    ,@paramVal    nvarchar (100) 
    ,@paramName    nvarchar (100) 
    ,@paramType    nvarchar (100) 
    ,@tempParam    sql_variant 

    declare @parameterList table (
     RowID   int identity (1,1) 
    ,ParameterValue nvarchar (100) 
    ,ParameterName nvarchar (100) 
    ,ParameterType nvarchar (100) 
) 

    insert into @parameterList 
    values 
    ('10', 'Param1', 'int') 
    ,('test', 'Param2', 'nvarchar') 

    -- Process each parameter one at a time 
    declare ParameterCursor cursor fast_forward for 
    select ParameterValue, ParameterName, ParameterType 
    from @parameterList 
    order by RowID 

    open ParameterCursor 

    fetch next from ParameterCursor into @paramVal, @paramName, @paramType 

    if @@FETCH_STATUS = 0 
    set @completeCommand = @completeCommand + ' ' 

    while @@FETCH_STATUS = 0 
    begin 

    print @completeCommand 

    -- verify the datatype is correct 
    set @tempParam = case @paramType 
      when 'int' then CAST (@paramVal as int) 
      when 'float' then CAST (@paramVal as float) 
      when 'nvarchar' then CAST (@paramVal as nvarchar) 
      else 'NULL' 
     end 

    set @completeCommand = @completeCommand + @paramName + ' = ' + @paramVal + ',' 

    fetch next from ParameterCursor into @paramVal, @paramName, @paramType 
    end 

    close ParameterCurosr 
    deallocate ParameterCursor 

を実行すると、そのユーザーがデータを入力した検証が「フロートするデータ型はnvarcharを変換エラー」エラーを取得していますデータがコマンド文字列に追加される前に期待されるデータ型と一致します。なぜ上記のコードが失敗するかについてのフィードバックは非常に高く評価されます。

乾杯、 ジョー

+0

基本的な欠陥 - データ型のユーザー入力に依存しています。私が「NVARCHAR」としてデータにタグ付けしているからといって、それはそれを意味するものではありません。ISNUMERICを使用して数値データ型にキャストする前に確認することを検討する必要があります。 –

+0

それは本当かもしれません。しかし、それはcase文が正しいWHEN句を選択しなかった理由を説明していません。 –

+0

ISNUMERICは "IsAllDigits"関数ではないので注意してください。この記事を見てください(サイトに必要な無料登録):http://www.sqlservercentral.com/articles/IsNumeric/71512/ – Tony

答えて

6

問題は、その場合は、この文のフロートとなっている最高precidence、とのデータ型を返しますです。 CASE (Transact-SQL)およびData Type Precedence (Transact-SQL)を参照してください。

CASEを有効にするにはWHEN 'xzy' then CAST (@paramVal as sql_variant)を追加すると、CASEは戻り値の型としてsql_variantを使用します。

OR CASEを削除するなど、IF-ELSEを使用する:あなたは単純なケースの機能だった使用は何

IF @paramType='int' 
    set @tempParam = CAST (@paramVal as int) 
ELSE IF @paramType='float' 
    set @tempParam = CAST (@paramVal as float) 
ELSE IF @paramType='nvarchar' 
    set @tempParam = CAST (@paramVal as nvarchar) 
ELSE 
    set @tempParam = NULL 
+0

偽のWHEN句が機能しました。 –

0

。検索されたCase関数が機能するはずです(下記参照)。 私は非常に単純なクエリでそれを試してみた:私は同じエラーを取得しますが、次の午前のSQL Server 2005年

DECLARE @type VARCHAR(100) 
DECLARE @input VARCHAR(100) 
DECLARE @value SQL_VARIANT 

SET @type = 'varchar' 
SET @input = 'test' 

SET @value = CASE 
    WHEN @type = 'varchar' THEN @input 
    WHEN @type = 'int' THEN CAST(@input AS VARCHAR) 
END 

は、SQL Server 2008のドキュメントからです:

単純CASE機能:

  • input_expressionを評価し、指定された順序でWHEN句ごとにinput_expression = when_expressionを評価します。
  • TRUEと評価される最初のinput_expression = when_expressionのresult_expressionを返します。
  • input_expression = when_expressionがTRUEと評価されない場合、SQL Server 2005データベースエンジンは、ELSE句が指定されている場合はelse_result_expressionを返し、ELSE句が指定されていない場合はNULL値を返します。 Boolean_expression各WHEN句のために、指定された順序で

    • 評価:CASE関数を検索

  • TRUEと評価される最初のBoolean_expressionのresult_expressionを返します。
  • Boolean_expressionがTRUEと評価されない場合、ELSE句が指定されている場合はelse_result_expression、ELSE句が指定されていない場合はNULL値が返されます。

この場合、Simple CaseはすべてのCASTSを実行してから使用するかどうかを決定しますが、Searched Caseはブール式を評価して実行するCASTを決定します。これが解決策になるはずです。

そうでなければ、おそらくIF ... THEN ... ELSEを使うことができます。

+0

あなたが使用するWHENと返されるデータ型を決定する方法を引用する場合を除いて、私は同じ文書を引用します。ドキュメントでは、 "Simple CASE関数"の直前に移動し、 'result_expressionsとオプションのelse_result_expressionの型のセットの中で最高の優先度の型を返します。 'これがキーです:'返されるデータ型 'if文字列を返そうとすると、ケースが浮動小数点を返すと判断して(ここにあるように)、変換エラーが発生します。 –

+0

続きを読む...私の答えは言うように、sql_variantが返される型(浮動小数点よりも優先順位が高い)またはIF-ELSEを使用するようにCASEを変更します –

+0

これを試しましたが、同じエラーが発生しました –