2011-02-03 110 views
5

我正在错误使用CAST时,“错误转换数据类型为nvarchar浮动”运行以下数据转换错误的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 

当我试图做的是验证用户输入的数据在将数据添加到命令字符串之前匹配预期的数据类型。任何关于为什么上面的代码失败的反馈将不胜感激。

干杯, 乔

+0

基本缺陷 - 您依赖用户输入数据类型。仅仅因为我将数据标记为“NVARCHAR”,并不意味着它是。在转换为数字数据类型之前,您应该考虑使用ISNUMERIC进行确认。 – 2011-02-03 21:47:49

+0

这可能是对的。但是这并不能解释为什么案例陈述没有选择正确的WHEN条款。 – 2011-02-03 21:52:50

+0

小心,ISNUMERIC不是“IsAllDigits”函数。看看这篇文章(免费注册到网站需要):http://www.sqlservercentral.com/articles/IsNumeric/71512/ – Tony 2011-02-03 21:53:02

回答

6

的问题是,案件将具有最高precidence,这是浮动的这一说法返回的数据类型。见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 
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的文档:

简单的例子功能:

  • 评估input_expression,然后按照指定的顺序评估每个WHEN子句的input_expression = when_expression。
  • 返回第一个input_expression = when_expression的值为TRUE的结果表达式。
  • 如果没有input_expression = when_expression的计算结果为TRUE,则SQL Server 2005数据库引擎在指定ELSE子句时返回else_result_expression,如果未指定ELSE子句,则返回NULL值。

CASE搜索功能:

  • 求值,按指定的顺序,逻辑表达式对每个WHEN子句。
  • 返回计算结果为TRUE的第一个布尔表达式的result_expression。
  • 如果没有布尔表达式计算结果为TRUE,则数据库引擎在指定ELSE子句时返回else_result_expression;如果未指定ELSE子句,则返回NULL值。

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

否则,您可以使用IF ... THEN ... ELSE,如另一个答案中提出的。