【问题标题】:Don't include variable in SQL WHERE clause if it is null如果 SQL WHERE 子句为空,则不要在该子句中包含变量
【发布时间】:2012-12-25 03:35:39
【问题描述】:

我在 SQL 中有一个查询,目前如果用户在文本框中输入的所有值都为空,那么当他们单击搜索时,它只会返回整个表。

SELECT Column Names
FROM TableName
WHERE
        FirstName LIKE '%' + @FirstName + '%'
        OR Surname LIKE '%' + @Surname + '%'
        OR City LIKE '%' + @City + '%'
        OR County LIKE '%' + @County + '%'

但是,如果在搜索时没有输入任何内容,我想要做的是不包括例如FirstName。因此,如果有人决定在City 中输入“London”,那么它将只返回那些包含伦敦的结果。同样,如果他们输入了“John”和“London”,那么我希望所有在伦敦打电话给 John 的人都可以返回。

【问题讨论】:

    标签: c# asp.net sql search


    【解决方案1】:

    所以你只想考虑@FirstName 是否有值?你可以通过改变来做到这一点

    FirstName LIKE '%' + @FirstName + '%'
    

    到这里

    (@FirstName = '' OR FirstName LIKE '%' + @FirstName + '%')
    

    当然,如果@FirstName 以 null 而不是空字符串的形式出现,那么它会是

    (@FirstName IS NULL OR FirstName LIKE '%' + @FirstName + '%')
    

    【讨论】:

      【解决方案2】:
      (FirstName LIKE '%' + @FirstName + '%' OR @FirstName IS NULL )
      

      【讨论】:

      • @Brad 你觉得怎么样?如果 FirstName 为 NULL,它将包括所有可能的名字。如果 FirstName 是 '' 那么它将拉入 "FirstName Like '%%'" 的所有内容,这也会拉入所有内容。为了搞砸它,他们必须输入一个空格。你 LTRIM(RTRIM()) FirstName 来弥补这一点,但这是正确的。
      • 撤销! (哦等等……除非有修改,否则目前无法更改投票,抱歉)
      【解决方案3】:

      这比较麻烦,但根据数据集的大小和索引,您可以通过这条路线获得一些性能提升。

      Declare @FirstName Nvarchar(10),
              @SurName Nvarchar(10),
              @City Nvarchar(10),
              @County Nvarchar(10),
              @SQL Nvarchar(Max),
              @OrCriteria Nvarchar(Max) = ''
      
      Set     @SQL = 'Select  Column Names
                      From    TableName '
      
      If      @FirstName Is Not Null
      Begin
              Set     @OrCriteria = @OrCriteria + 'FirstName Like ''%''' + @FirstName + '''%'' Or '
      End         
      
      If      @Surname Is Not Null
      Begin
              Set     @OrCriteria = @OrCriteria + 'Surname Like ''%''' + @Surname + '''%'' Or '
      End     
      
      If      @City Is Not Null
      Begin
              Set     @OrCriteria = @OrCriteria + 'City Like ''%''' + @City + '''%'' Or '
      End     
      
      If      @County Is Not Null
      Begin
              Set     @OrCriteria = @OrCriteria + 'County Like ''%''' + @County + '''%'' Or '
      End         
      
      If      @OrCriteria <> ''
      Begin
              Set     @SQL = @SQL + 'Where (' + Left(@OrCriteria,Len(@OrCriteria)-4) + ')'
      End
      
      Exec    sp_executeSQL @SQL
      

      【讨论】:

      • 谢谢,但我并不真正理解这一点,因为这对我来说似乎很复杂,但我得到了与 Brad 的解决方案相同的错误。
      • 在声明变量时收到错误,这很奇怪。它适用于 SSMS,因此它必须是您正在使用的位置/方法。我理解如果它对您没有意义,请不要使用它。它之所以有用是因为它在技术上比其他解决方案具有更高的性能,因为您只在 where 条件中包含了您需要的列。使用此解决方案,如果 @FirstName 为 Null,则无需对列运行逻辑来检查它,因为假定它们都应该包含在内。
      • 此方法在创建具有多个表的大型复杂查询时非常有用。例如,如果您有一个标准变量需要连接到另一个大表,但从技术上讲,除了作为剔除方法之外,您不需要该表。如果您有这样的场景,有时您可能不需要该变量,您可以使用动态 SQL 来构建查询,从而完全避免连接到该表。使用这种方法,我已经成功地显着提高了某些查询的性能。干杯!
      【解决方案4】:

      其他答案是正确的,但我认为我会帮助您将一些内容放回您的原始查询中:

       SELECT Column Names
      FROM TableName
      WHERE
        ((@FirstName is null and FirstName like '%') or (isnull(FirstName ,0) = @FirstName)) and
        ((@Surname is null and Surname like '%') or (isnull(Surname ,0) = @Surname)) and
        ((@City is null and City like '%') or (isnull(City ,0) = @City)) and
        ((@County is null and County like '%') or (isnull(County,0) = @County))
      

      你应该可以复制粘贴出来

      吉姆

      【讨论】:

      • +1 但原始问题在每个城市、名字、姓氏、国家/地区之间使用“或”...
      • 好的,这几乎可以了。如果我使用 AND 那么它显然需要所有文本框在其中具有某种价值。输入所有值后,它将仅返回输入的正确客户。但是,它不允许我只输入“John”,然后只列出所有名字为“John”的客户。如果我将其更改为 OR,那么如果我输入“John”,那么他的姓氏为“Smith”,City 为 Southampton,County 为 Hampshire,那么它将列出姓氏为“Smith”等的名为 John 的所有人。例如,我得到“ Dave Smith”也是因为“Smith”是作为姓氏输入的。
      • 也许其中最大的问题是,例如,如果我进入 Hampshire,然后列出来自 Hampshire 的每个人。这意味着要找到我搜索的名字的人,我必须遍历 Hampshire 的所有人。
      • 嗯,我还注意到此解决方案删除了​​输入例如名称以“J”开头的每个人的功能,如果您要输入“Joh”,然后输入“John”仍应列出。
      • 其实,是的,AND 是对的。我已经把它改成了这个,现在它可以工作了:D(由于某种原因我不能发布“@”符号,所以我已经删除了它们)。 ((FirstName LIKE FirstName + '%') or (isnull(FirstName ,0) FirstName)) AND ((Surname LIKE Surname + '%') or (isnull(Surname ,0) = Surname)) AND ((City LIKE City + '%') or (isnull(City ,0) = City)) AND ((County LIKE County + '%') or (isnull(County,0) = @County))
      【解决方案5】:
      declare @sql as varchar(300)
      , @FirstName as varchar(50)
      , @Surname as varchar(50)
      , @City as varchar(50)
      , @County as varchar(50)
      
      set  @FirstName = 'myname'
      set  @Surname = 'mylastname'
      set  @City = null
      set  @County = 'county'
      
      set @sql= 'SELECT Column_Names
      FROM TableName ' +    
       case when rtrim(ltrim(isnull(@FirstName,'') + isnull(@Surname,'') + isnull(@City,'') + isnull(@County,''))) = '' then '' else 'where ' end
       + coalesce('FirstName LIKE ''%' + nullif(@FirstName,'')+ '%'' or ', '') +
              + coalesce('Surname LIKE ''%' + nullif(@Surname,'')+ '%'' or ', '') +
              + coalesce('City LIKE ''%' + nullif(@City,'')+ '%'' or ', '') +
              + coalesce('County LIKE ''%' + nullif(@County,'')+ '%''', '')
      
          select @sql
      

      @sql的内容应该是

      SELECT Column_Names  FROM TableName where FirstName LIKE '%myname%' or Surname LIKE %mylastname%' or County LIKE '%county%'
      

      然后要使用您创建的动态字符串,您需要Exec @Sql

      【讨论】:

      • 谢谢,但我收到“关键字 'declare' 附近的语法不正确。”当我使用这个时:S
      【解决方案6】:

      在 SQL Server 中存在 ISNULL()

      然后

      SELECT Column Names
      FROM TableName
      WHERE
              FirstName LIKE '%' + ISNULL((@FirstName, '') + '%'
              OR Surname LIKE '%' + ISNULL((@Surname, '') + '%'
              OR City LIKE '%' + ISNULL((@City, '') + '%'
              OR County LIKE '%' + ISNULL((@County, '') + '%'
      

      【讨论】:

        猜你喜欢
        • 2012-07-16
        • 2018-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-15
        • 2023-01-06
        相关资源
        最近更新 更多