【问题标题】:Search by parameter only if user enters a value仅当用户输入值时按参数搜索
【发布时间】:2009-02-13 20:45:14
【问题描述】:

我想重写此查询,以便如果 @UserName 传入一个空值,那么它将 Client_User 排除在搜索条件之外。如果用户在网络表单的用户名文本框中输入名称,我只希望它按名称搜索。我不知道该怎么做。

select * from weblogs.dbo.vwlogs 
where Log_time between @BeginDate and @EndDAte 
and  client_user=@UserName

【问题讨论】:

    标签: asp.net sql sql-server


    【解决方案1】:

    从 weblogs.dbo.vwlogs 中选择 *,其中 @BeginDate 和 @EndDate 之间的 Log_time 和 (@UserName 为 NULL 或 client_user=@UserName)

    【讨论】:

      【解决方案2】:
      select * 
      from weblogs.dbo.vwlogs 
      where Log_time between @BeginDate and @EndDAte 
        and (client_user=@UserName or @UserName IS null)
      

      【讨论】:

      • @UserName IS NULL 而不是@UserName = NULL
      • 除非“SET ANSI_NULLS = OFF”——恕我直言,这是魔鬼的杰作!
      【解决方案3】:

      Kristen 的解决方案可行,但如果您需要性能,请不要这样做,因为该计划将仅针对第一个条件进行缓存。

      因此,如果首先使用 NULL 参数调用您的过程,则该查询将被缓存。

      如果您需要更高的性能,请使用 IF 语句并创建两个不同的查询。

      在更复杂的查询中,事件 sp_execsql 会更快。

      【讨论】:

      • 我同意,但是如果代码在存储过程中,那么参数嗅探可能会有所帮助......如果它只是动态 SQL,那么所有关于缓存的赌注无论如何都不会发生 - 或者,正如你所说,最好还是使用带有显式生成的 WHERE 子句的 sp_ExecuteSQL,以便单独缓存每个变体
      • 是的,无论如何,你的答案是对的,我已经升级了。我的回答只是附加信息...
      【解决方案4】:

      最好的解决方案是利用 sp_execute_sql。例如:

      --BEGIN SQL
      declare @sql nvarchar(4000)
      
      set @sql = 
      'select * from weblogs.dbo.vwlogs 
      where Log_time between @BeginDate and @EndDate'
      + case when @UserName is null then '' else 'and client_user = @UserName' end
      
      sp_execute_sql
      @sql
      , @params = '@UserName varchar(50)'
      , @UserName = @UserName
      --END SQL
      

      正如 muerte 所说,这将带来性能优势。根据 BOL:

      当参数值对语句的更改是唯一的变化时,可以使用 sp_executesql 代替存储过程多次执行 Transact-SQL 语句。因为 Transact-SQL 语句本身保持不变并且只有参数值发生变化,所以 Microsoft® SQL Server™ 查询优化器可能会重用它为第一次执行生成的执行计划

      【讨论】:

      • 嗯,这对于 2 个参数来说可能是矫枉过正。不过,当你有更多时很有用。
      • 不确定 2 个参数的过度杀伤力。为“@UserName IS NULL OR COL=@UserName”SProc 缓存的查询计划将基于其首次使用。这可能会破坏替代 @UserName 存在/不存在场景的性能。 sp_ExecuteSQL 直接从 APP 可能是最好的 - 但仍需要 SELECT 权限
      猜你喜欢
      • 2017-07-02
      • 2020-12-30
      • 2011-02-02
      • 1970-01-01
      • 2021-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-03
      相关资源
      最近更新 更多