【问题标题】:Set where clause basis parameter value in SQL Server在 SQL Server 中设置 where 子句基础参数值
【发布时间】:2021-11-26 09:02:10
【问题描述】:

我希望在使用 WHERE 子句基础 @USER_ID 在我的 SQL 服务器查询中记录的用户输入时设置一个条件,但我想我在这里遗漏了一些重要的东西。

DECLARE @USER_ID NVARCHAR(255) = 'a,b,c' -- will be multi-select parameter; can be null as well 


select * from <table_name>

{
if:      @USER_ID is NULL then no WHERE condition
else:    WHERE <table_name>.<col_name> in (SELECT item FROM SplitString(@USER_ID,','))
}

有人可以帮忙吗?

【问题讨论】:

标签: sql-server tsql if-statement where-clause


【解决方案1】:

我个人建议切换到表类型参数,那么你根本不需要使用STRING_SPLIT。不过,我不打算在这里介绍所述类型参数的创建;那里已经有很多了,文档也足以解释它。

至于问题,如果我们要使用STRING_SPLIT,您将使用如下方法:

SELECT {Your Columns} --Don't use *
FROM dbo.YourTable YT
WHERE YT.YourColumn IN (SELECT SS.Value
                        FROM STRING_SPLIT(@USER_ID,',') SS)
   OR @USER_ID IS NULL
OPTION (RECOMPILE);

OPTION 子句中的RECOMPILE 很重要,因为@USER_ID 具有值NULL 的查询可能与不具有值的查询非常不同。

可以使用动态 SQL 方法,但对于一个参数,我怀疑除了微不足道的好处之外还有什么好处。使用上述方法对其他人来说也更容易理解,并且每次运行查询时生成计划的成本对于这样一个简单的查询来说应该很小。

使用表类型参数,使用UNION ALL 查询实际上可能会更高效(假设您在YourColumn 上有一个可用索引),如下所示:

SELECT {Your Columns} --Don't use *
FROM dbo.YourTable YT
     JOIN @Users U ON YT.YourColumn = U.UserId
UNION ALL
SELECT {Your Columns} --Don't use *
FROM dbo.YourTable YT
WHERE NOT EXISTS (SELECT 1 FROM @Users U);

【讨论】:

    【解决方案2】:

    你可以完全避免在这里使用STRING_SPLIT

    WHERE ',' + @USER_ID + ',' LIKE '%,' + <table_name>.<col_name> + ',%'
    

    【讨论】:

    • STRING_SPLIT 至少不会是 SARGable,而上述情况不会?
    • @Larnu 很好,但STRING_SPLIT 涉及生成动态表值函数结果,它也必须有自己的开销。
    • 是的,我承认表类型参数可能是 best™ 解决方案。
    • 我原以为 string_split 的性能会更高,构建值表的一次性开销对于扫描索引的 IO 成本来说可以忽略不计,而不是直接查找行
    【解决方案3】:

    如果@UserID 为NULL,则执行条件(1=1),这总是正确的。如果@UserID 不为 NULL,则执行 OR 条件,其中 (a, b, c) 中的所有 都存在。

    SELECT * 
    FROM <table_name>
    WHERE (1=1)
        AND ((@USER_ID IS NULL AND (1=1)) -- always true
            OR (<table_name>.<col_name> in (SELECT [value] FROM SplitString(@USER_ID,',')))
        )
    

    【讨论】:

    • 感谢您提供答案。您能否编辑您的答案以包括对您的代码的解释?这将有助于未来的读者更好地了解正在发生的事情,尤其是那些刚接触该语言并难以理解概念的社区成员。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-18
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多