2016-07-05 53 views
0

我从VBA执行存储过程时遇到问题:我想传入列名作为参数的字符串,然后使用case语句在数据中选择实际的列名称。将动态列名传递到SQL Server时出现数据类型错误

当我通过的列名(@FACTOR)是一个整数,而不是当它是一个varchar时,此查询正常工作。我得到一个转换错误:

将数据类型nvarchar转换为float时出错。

这里是我的代码:

WITH T0 AS (
     SELECT DISTINCT 
     CASE @FACTOR 
      WHEN 'DRVREC' THEN DRIVINGRECORD --OK 
      WHEN 'POAGE' THEN POAGE 
      WHEN 'ANNUALKM' THEN AMC_VH_ANNL_KM 
      WHEN 'DAILYKM' THEN AMC_VH_KM_TO_WRK 
      WHEN 'RATETERR' THEN AMC_VH_RATE_TERR --OK 
      WHEN 'BROKERNAME' THEN MASTERBROKER_NAME 
      WHEN 'DRVCLASS' THEN DRIVINGCLASS -- OK 
      WHEN 'VEHAGE' THEN VEH_AGE -- OK 
      WHEN 'YEARSLIC' THEN YRSLICENSE 
      WHEN 'COVERAGECODE' THEN COVERAGECODE 
      ELSE NULL END AS FACTOR FROM DBO.Automation_Data 
     ), 
    ... 
    ... 

也许下面的例子更简洁:

DECLARE @FACTOR varchar(50) 
SELECT @FACTOR = 'NOT_A_VARCHAR' 

SELECT CASE @FACTOR 
    WHEN 'A_VARCHAR' THEN COLUMNNAME1 
    WHEN 'NOT_A_VARCHAR' THEN COLUMNNAME2 
    ELSE NULL END AS FACTOR FROM dbo.myTable 

^这工作,但如果@FACTOR = 'A_VARCHAR'然后我得到的错误。

在此先感谢!

UPDATE **************:

这似乎是案件陈述本身的问题?

当我在case语句中只有varchar选项时,查询运行。当我对案例陈述的第二部分取消注释时,我得到错误。

DECLARE @FACTOR varchar(50) 
SELECT @FACTOR = 'A_VARCHAR' 

SELECT CASE @FACTOR 
    WHEN 'A_VARCHAR' THEN COLUMNNAME1 
    --WHEN 'NOT_A_VARCHAR' THEN COLUMNNAME2 ELSE NULL 
    END AS FACTOR FROM dbo.myTable 
+0

把转换(nvarchar的周围所有的列选择 – artm

+0

感谢您的建议铸造的无金额或转换似乎工作见我的更新中,问题似乎是以某种方式来自Case声明 – stobin

+0

确定了 - 您的评论其实是正确的:我在测试时没有转换每个案例的选择,因为我认为它不是必需的,但它看起来像即使一个case选项没有被选中,它仍然需要被转换为NVARCHAR。谢谢! – stobin

回答

1

当您从多个列中选择多个列作为单个列时,SQL会将结果作为最高优先级类型返回。当从多种数据类型返回单个结果时,聚合等也是如此。

如果您尝试下面的代码例如,3rd选择将返回您收到的错误,因为它会尝试将abc转换为int(更高优先级)。如果将@V设置为'123',错误将消失,因为从'123'到int/float的转换工作。当您检查结果的'BaseType'时,可以看到它显示混合类型的最高优先级数据类型。

DECLARE @F int = 1 --if you use float here error message will show ...'abc' to data type float. 
DECLARE @V varchar(5) = 'abc' 

DECLARE @O varchar = '1' 

SELECT CASE WHEN @O = '1' THEN @F ELSE @V END --no error 

SELECT SQL_VARIANT_PROPERTY((SELECT CASE WHEN @O = '1' THEN @F ELSE @V END), 'BaseType') --int/float 

SET @O = '2' 

SELECT CASE WHEN @O = '1' THEN @F ELSE @V END --error: Conversion failed when converting the varchar value 'abc' to data type int. 

当您将所有选择转换为nvarchar时,nvarchar成为最高优先级数据类型,因此它工作正常。但是如果你知道你的一些列是浮点数并且其中一些是nvarchar,那么你只需要将浮点列转换为nvarchar。因此,这也能发挥作用:。

SET @O = '2' 
SELECT CASE WHEN @O = '1' THEN CONVERT(NVARCHAR(5), @F) ELSE @V END 

SQL Data Type Precedence

相关问题