Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在SQL Server动态查询中将列名作为变量传递?_Sql_Sql Server - Fatal编程技术网

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

如何在SQL Server动态查询中将列名作为变量传递?,sql,sql-server,Sql,Sql Server,我有下面的查询,它给出了每列的不同值的计数。但我需要在查询中添加where子句条件,例如column1='abc'。我使用这个通用查询,以便通过传递表名,也可以对其他表使用相同的查询 DECLARE @query VARCHAR(MAX) SELECT @query = 'SELECT ' + SUBSTRING((SELECT ',' +'COUNT(DISTINCT(' + column_name + ')) AS ' + column_name + ' ' FRO

我有下面的查询,它给出了每列的不同值的计数。但我需要在查询中添加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)

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

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

这应该是你想要的。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语句很好地格式化查询


如果您不明白,请询问。

'FROM'@tname将在此处创建语法错误。你也应该把你的陈述参数化其中,“+”列_name“+”=“++@acc_num+`对注入是完全开放的。在sp_executesql中使用参数化语句。此外,删除字符串的第一个字符的常用方法是STUFF{String,1,1,。它比substring更可靠。此查询将仅由内部团队使用。而不是应用程序的一部分。我只需要编写此查询来查看结果内部或外部,这不会给您错误编码实践的原因。注意:当您必须开始使用动态sql传递列和表名时,在e设计。感谢您的回答,如果我需要为所有不同的@Acc_Num获得相同的结果,该怎么办?因此,如果表中@cname列有10个不同的值。它应该返回10行,每个列都有不同的值。就像返回给定的@Acc_Num移动位置一样,更改SELECT并在dynam中添加一个GROUP BYic语句。就像你将使用普通的非动态语句@viveknuna一样。无需传递第二个参数。请帮助你,你需要能够支持代码@viveknuna,而不是我。正如我所说,如果你不理解,请询问你不理解的内容。但请不要要求我为每个sce提供示例nario,这是关于现有答案的。一个小小的支持。我需要在返回的结果中使用cname列的值。我尝试了,但没有做到。OP没有问如何解决注射问题。我只回答了被问到的问题。因此,因为OP没有问如何修复注射,所以你不应该问?如果你的y上有一个洞我们的墙和你被要求修复这个漏洞,你会用一张纸盖住它,假装问题已经解决了吗?你看不到它了,或者正确地填充了它?不解决一个巨大的安全漏洞并不能让这成为一个好的答案。你只是假设存在注射风险。问题没有说明输入是否存在或如何存在e在前端清理,或者甚至有输入。这可能是从数据库获取其变量值的无人值守应用程序的一部分。这是一个非常糟糕的假设。当@acc_num可以作为参数时,没有理由使用='+@acc_num+。这种态度是注入仍然如此普遍的原因,也是人们不这么做的原因不知道如何避免它;因为应该更清楚的人自己并没有遵循好的标准。通过提供一个好的答案来教育人们与提供一个正确的答案同样重要。