【问题标题】:What is best way to search from optional parameter to SQL query in a stored procedure?在存储过程中从可选参数搜索到 SQL 查询的最佳方法是什么?
【发布时间】:2018-10-07 11:20:33
【问题描述】:

当涉及到在 SQL 存储过程中搜索带有可选参数的记录时,这两个查询中。两者都返回相同的结果。考虑到性能,您将使用哪一个以及为什么?

我有一个存储过程,它有多个搜索参数,将在多个表中搜索,并连接来自一个巨大的记录集。

DECLARE @EventName VARCHAR(100)
--SET @EventName = ''
--SET @EventName = NULL
SET @EventName = 'Coffee in Coffee Bean'

-- Query - 1
SELECT * 
FROM EventDetails
WHERE 
    1 = CASE 
           WHEN @EventName IS NULL OR @EventName = '' THEN 1 
           WHEN EventName LIKE '%'+ @EventName +'%' THEN 1 ELSE 0 
        END

-- Query - 2
SELECT * 
FROM EventDetails
WHERE 
    EventName LIKE '%' + CASE 
                            WHEN LEN(LTRIM(@EventName)) > 0 
                               THEN @EventName 
                               ELSE EventName 
                         END + '%' 

【问题讨论】:

  • 使用可选参数(我知道它可能很难看)性能的最佳选择是动态 SQL。你可以用它省略整个过滤器。
  • @EzLo:我知道,但这将是最危险的 sql,它可以创建类似 sql 注入(如果有人在参数值中输入查询)会给出整个表输出。
  • 如果您有两匹马,并且您想知道哪两匹马更快,那么赛马 - 请参阅 Eric 的 Which is faster? Lippert 了解更多背景
  • @marc_s:问题是记录还没有在系统中,它的创建需要6个月左右...但是不能跑马:)只是在之前判断它们:)
  • 谢谢@marc_s。当我对数百万条记录的表运行此查询时,第一个查询比第二个查询快得多。谢谢!

标签: sql-server tsql stored-procedures sql-like optional-parameters


【解决方案1】:

您可以通过编写单个查询来尝试此操作

SELECT * 
FROM EventDetails
WHERE ((@EventName IS NULL OR @EventName) OR (EventName LIKE '%'+ @EventName +'%'))

【讨论】:

    【解决方案2】:

    我的钱花在这个上:

    IF ISNULL(@EventName), '') = ''
      SELECT * FROM EventDetails
    ELSE
      SELECT * FROM EventDetails WHERE EventName = '%' + @EventName + '%'
    

    【讨论】:

      【解决方案3】:

      如果不能考虑动态SQL,那就尽量少用函数和数据篡改。最常见的方法如下:

      DECLARE @OptionalFilter1 INT
      DECLARE @OptionalFilter2 VARCHAR(100)
      -- ...
      DECLARE @OptionalFilterN BIT
      
      SELECT
          YourColumns
      FROM
          YourTable AS T
      WHERE
          (@OptionalFilter1 IS NULL OR @OptionalFilter1 = T.Filter1Column) AND
          (@OptionalFilter2 IS NULL OR @OptionalFilter2 = T.Filter2Column) AND
          -- ...
          (@OptionalFilterN IS NULL OR @OptionalFilterN = T.FilterNColumn)
      

      你的例子是:

      DECLARE @EventName VARCHAR(100) = 'Coffee in Coffee Bean'
      
      SELECT
          * 
      FROM 
          EventDetails AS E
      WHERE
          (@EventName IS NULL OR E.Event LIKE '%' + @EventName + '%')
      

      如果这将在一个过程中结束,请考虑在带有许多过滤器的查询上使用OPTION (RECOMPILE) 和/或将存储过程参数分配给新的局部范围变量以防止参数嗅探。您可以阅读有关参数嗅探问题(与您的示例类似)in this post

      【讨论】:

      • 这是所有查询之间的最佳答案,您的答案给出了最快的结果。谢谢! @EzLo
      猜你喜欢
      • 2019-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-19
      • 1970-01-01
      • 2011-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多