在CASE语句中使用CAST时的数据转换错误

时间:2011-02-03 21:40:08

标签: sql sql-server tsql sql-server-2008

运行以下

时出现错误'将数据类型nvarchar转换为float时出错'
     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

我要做的是在将数据添加到命令字符串之前验证用户输入的数据是否与预期的数据类型匹配。关于上述代码失败原因的任何反馈将不胜感激。

干杯, 乔

2 个答案:

答案 0 :(得分:6)

问题是CASE将返回具有最高预测的数据类型,该语句的浮点数为float。见CASE (Transact-SQL)Data Type Precedence (Transact-SQL)

要使CASE工作,请添加一个伪WHEN 'xzy' then CAST (@paramVal as sql_variant),这将导致CASE使用sql_variant作为返回数据类型。

或删除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

答案 1 :(得分:0)

您使用的是简单案例功能。搜索案例功能应该有效(见下文)。 我刚刚在一个非常简单的查询中尝试过它:

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 2005上我收到同样的错误,但以下内容来自SQL Server 2008 doc:

简单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值。

搜索CASE功能:

  • 按照指定的顺序评估每个WHEN子句的Boolean_expression。
  • 返回第一个求值为TRUE的Boolean_expression的result_expression。
  • 如果没有Boolean_expression计算为TRUE,则数据库引擎在指定ELSE子句时返回else_result_expression,如果未指定ELSE子句则返回NULL值。

如果这是真的,那么Simple Case将执行所有CASTS,然后决定使用qhich,而Searched Case将评估布尔表达式,然后决定执行哪个CAST。这应该是解决方案。

否则,您可以使用IF ......那么......正如另一个答案所建议的那样。