performance - 如果 IN 子句没有值,如何返回所有行?

标签 performance tsql sql-server-2005 sql-like in-clause

以下是示例查询。

CREATE PROCEDURE GetModel
(
    @brandids varchar(100), -- brandid="1,2,3"
    @bodystyleid varchar(100) -- bodystyleid="1,2,3"

)
AS
   select * from model
   where brandid in (@brandids) -- use a UDF to return table for comma delimited string
   and bodystyleid in (@bodystyleid)

我的要求是,如果 @brandids@bodystyleid 为空,则查询应返回该条件下的所有行。

请指导我如何做到这一点?还建议如何编写此查询以优化性能。

最佳答案

无论如何,您都需要动态 SQL 或拆分函数,因为 IN ('1,2,3')IN (1,2,3 )

拆分功能:

CREATE FUNCTION dbo.SplitInts
(
   @List       VARCHAR(MAX),
   @Delimiter  CHAR(1)
)
RETURNS TABLE
AS
   RETURN ( SELECT Item = CONVERT(INT, Item) FROM ( 
     SELECT Item = x.i.value('(./text())[1]', 'int') FROM ( 
       SELECT [XML] = CONVERT(XML, '<i>' + REPLACE(@List, @Delimiter, '</i><i>') 
       + '</i>').query('.') ) AS a CROSS APPLY [XML].nodes('i') AS x(i)) AS y
     WHERE Item IS NOT NULL
   );

代码变成这样:

SELECT m.col1, m.col2 FROM dbo.model AS m
LEFT OUTER JOIN dbo.SplitInts(NULLIF(@brandids, ''), ',') AS br
ON m.brandid = COALESCE(br.Item, m.brandid)
LEFT OUTER JOIN dbo.SplitInts(NULLIF(@bodystyleid, ''), ',') AS bs
ON m.bodystyleid = COALESCE(bs.Item, m.bodystyleid)
WHERE (NULLIF(@brandids, '') IS NULL OR br.Item IS NOT NULL)
AND (NULLIF(@bodystyleid, '') IS NULL OR bs.Item IS NOT NULL);

(请注意,我在这里添加了很多 NULLIF 处理...如果这些参数没有值,您应该传递 NULL,而不是“空白”。)

由于参数嗅探而导致错误计划的可能性要小得多的动态 SQL 将是:

DECLARE @sql NVARCHAR(MAX);

SET @sql = N'SELECT columns FROM dbo.model
WHERE 1 = 1 '
+ COALESCE(' AND brandid IN (' + @brandids + ')', '')
+ COALESCE(' AND bodystyleid IN (' + @bodystyleid + ')', '');

EXEC sp_executesql @sql;

当然,正如@JamieCee 指出的那样,动态 SQL 可能容易受到注入(inject)攻击,如果您在任何地方搜索动态 SQL,就会发现这一点。因此,如果您不信任自己的输入,则需要防范潜在的注入(inject)攻击。就像您在应用程序代码中组装临时 SQL 一样。

当您迁移到 SQL Server 2008 或更高版本时,您应该查看 table-valued parameters (example here)。

关于performance - 如果 IN 子句没有值,如何返回所有行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10758966/

相关文章:

sql-server-2005 - ORDER BY 5 DESC 是什么意思?

linux - Linux Mint 上神秘的 find 命令占用内存

Java : Creating chunks of List for processing

javascript - 如何使用 Excel JavaScript API office Add-IN 最大限度地提高表行添加 50K+ 行的性能

sql - 我可以在 SQL Server 2005 中选择查询的 where 条件中使用列号而不是列名吗?

sql - 空值列和不存在 T-sql

c++ - C++中字符串和char数组声明的时间复杂度有什么区别?

sql-server - T-SQL 中的 CASE 语句或函数具有更好的性能

MySQL 查询 : 3 tests passed, 1 失败

sql - 具有默认值的列和具有默认约束的列有什么区别?