我可以在where子句中使用标准列的参数

时间:2018-01-04 20:34:38

标签: sql-server

英文:

我想将列名和条件作为参数传递给我的应用程序中的查询。

在SQL中:

ALTER PROCEDURE [dbo].[Test] 
    @Col nvarchar,
    @ColValues nvarchar
AS
BEGIN
    SELECT * FROM PEOPLE
    WHERE @Col IN (@ColValues)

SQL Server接受此查询,但它不返回正确的值。例如,如果我将@Col作为“LastName”传递,将@ColValues传递为“Smith,Jones”,则即使存在这些LastNames,查询也不会返回任何记录。

执行此操作的唯一方法是使用动态SQL吗?我已经查看了之前提出的所有SO问题,但没有人处理过这个具体问题。

3 个答案:

答案 0 :(得分:2)

当然,动态SQL会更高效,我不建议在大型表上使用它。但是,它可以在没有动态的情况下完成。

示例

Declare @YourTable Table ([Column1] varchar(50),[Column2] varchar(50),[Column3] varchar(50),[Column4] varchar(50),[Column5] varchar(50))
Insert Into @YourTable Values 
 ('Dog',456,'Long','Short','Small')
,('Car',454,'Blue',NULL,NULL)
,('Fruit',466,'Apple','Pear',NULL)

Declare @Col varchar(50) = 'Column3'
Declare @ColValues varchar(100) = 'Blue,Apple'

Select Distinct A.*
 From @YourTable A
 Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
 Cross Apply (
                Select Field = a.value('local-name(.)','varchar(100)')
                      ,Value = QuoteName(a.value('.','varchar(max)'))
                 From  B.XMLData.nodes('/row')  as C1(n)
                 Cross Apply C1.n.nodes('./@*') as C2(a)
                 Where a.value('local-name(.)','varchar(100)') = @Col
             ) C
  Where charindex(C.Value,'['+replace(@ColValues,',','][')+']')>0

<强>返回

Column1 Column2 Column3 Column4 Column5
Car     454     Blue    NULL    NULL
Fruit   466     Apple   Pear    NULL

答案 1 :(得分:0)

有一个变容器......但只有当过滤器中可能的列数固定且很小时才会出现。

基本思路是,对于列值,您使用Table作为输入参数,让我们说&#39; @ColValues&#39;。

https://docs.microsoft.com/en-us/sql/relational-databases/tables/use-table-valued-parameters-database-engine

然后你使用像

这样的东西
SELECT *
FROM People
WHERE 
(@ColName = 'LastName' and EXISTS (SELECT 1 FROM @ColValues WHERE ColValue = People.LastNAme)
OR
(@ColName = 'FirstName' and EXISTS (SELECT 1 FROM @ColValues WHERE ColValue = People.FirstName)
OR
(@ColName = 'FullName' and EXISTS (SELECT 1 FROM @ColValues WHERE ColValue = People.FullName)
OR
...

同时检查表现。

答案 2 :(得分:0)

我尝试了这些不同的方法,最后在这种情况下决定动态SQL是最好的方法。感谢您的想法,他们可能会在其他地方派上用场。