将动态列名称传递到SQL Server

时间:2016-07-05 23:28:00

标签: sql sql-server tsql

我在从VBA执行存储过程时遇到了一个问题:我想传入一个列名作为参数的字符串,然后使用case语句在数据中选择实际的列名

当通过的列名(@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'那么我就会收到错误。

提前致谢!

更新**********************************:

案件陈述本身似乎是一个问题?

当我在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

1 个答案:

答案 0 :(得分:1)

当您从多个列中选择单个列时,SQL会将结果作为最高优先级类型返回。当从多种数据类型返回单个结果时,与合并等相同。

如果你尝试下面的代码,例如,3rd select将返回你得到的错误,因为它试图将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成为最高优先级数据类型,因此它起作用。但是如果你知道你的一些列是float并且其中一些是nvarchar,你只需要将float列转换为nvarchar。所以这也会起作用:

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

请参阅SQL Data Type Precedence