如何在SQL Server中的动态查询中将列名作为变量传递?

时间:2019-04-02 19:42:35

标签: sql sql-server

我有以下查询,该查询给出了每一列的不同值的计数。但是我需要在查询中添加where子句条件,例如column1 ='abc'。我正在使用此通用查询,以便通过传递表名也可以对其他表使用同一查询。

DECLARE @query VARCHAR(MAX)

SELECT @query = 
    'SELECT ' + SUBSTRING((SELECT ',' +'COUNT(DISTINCT(' + column_name + ')) AS ' + column_name + ' '  
     FROM information_schema.columns
     WHERE table_name = 'table_name'
     FOR XML PAT('')), 2, 100000) + 'FROM table_name'

--PRINT(@query)
EXECUTE(@query)

我尝试将其传递如下。

WHERE 
    table_name = 'table_name' 
    AND column1 = 'abc'     -- compilation error, obviously

WHERE 
    table_name = 'table_name' 
    AND 'column1' = 'abc'   -- not working, because it will compare the string values column1 and abc. and both are not equal

然后我只是尝试使用以下查询,但这也不起作用,当我尝试打印时会生成错误的查询。

DECLARE @SQL NVARCHAR(MAX), @tname NVARCHAR(100), 
        @cname NVARCHAR(100), @acc_num NVARCHAR(50), @dp_code NVARCHAR(100)

SET  @cname = 'column_name';
SET @acc_num = 'xyz';
SET @tname = 'table_name';

DECLARE @query VARCHAR(MAX);

SET @SQL = ''
        ;with cols as (
        select Table_Schema, Table_Name, Column_Name, Row_Number() over(partition by Table_Schema, Table_Name
        order by ORDINAL_POSITION) as RowNum
        from INFORMATION_SCHEMA.COLUMNS
        )


SELECT @query = 
    'SELECT ' + SUBSTRING((SELECT ',' +'COUNT(DISTINCT(' + QUOTENAME(column_name, '') + ')) As ' + QUOTENAME(column_name, '')+ ' '
    + ' WHERE ' + 'column_name' + ' = ''' + @acc_num + ''''  
             FROM cols
             WHERE 
             table_name = @tname
             for xml path('')),2,200000)  +  'FROM' @tname
        --for xml path(''); 

PRINT @query
--execute (@query)

2 个答案:

答案 0 :(得分:0)

如果要在动态查询中使用WHERE子句,则必须将其放在动态查询中的FROM子句之后。

 ...
 for xml path('')),2,200000)  +  ' FROM '+ @tname
 + ' WHERE ' + 'column_name' + ' = ''' + @acc_num + ''''  

答案 1 :(得分:0)

这应该是您所追求的。在SQL中,您需要注意一些注释:

DECLARE @SQL nvarchar(max),
        @tname sysname, --note the datatype change
        @cname sysname, --note the datatype change
        @acc_num nvarchar(50),
        @dp_code nvarchar(100); --This is never used in your sample query
SET  @cname = 'column_name';
SET @acc_num = 'xyz';
SET @tname = 'table_name';


SET @SQL = N'SELECT ' + NCHAR(13) + NCHAR(10) +
             STUFF((SELECT N',' + NCHAR(13) + NCHAR(10) +
                           N'       ' + N'COUNT DISTINCT(' + QUOTENAME(C.Column_Name) + N') AS ' + QUOTENAME(C.Column_Name)
                    FROM INFORMATION_SCHEMA.COLUMNS C
                    WHERE C.Table_Name = @tname
                    ORDER BY C.ORDINAL_POSITION
                    FOR XML PATH(N'')),1,10,N'') + NCHAR(13) + NCHAR(10) +
             N'FROM ' + QUOTENAME(@tname) + NCHAR(13) + NCHAR(10) +
             N'WHERE ' + QUOTENAME(@cname) + N' = @Acc_Num;'

PRINT @SQL; --YOur debugging best friend
EXEC sp_executesql @SQL, N'@Acc_Num varchar(100)',@Acc_Num = @acc_num;

此参数改为使用sp_executesql对查询进行参数化,并很好地为您的PRINT语句设置格式。

如果您不理解,请请问