SQL Server 不区分大小写的查询

Posted

技术标签:

【中文标题】SQL Server 不区分大小写的查询【英文标题】:SQL Server case insensitive queries 【发布时间】:2015-07-23 16:18:53 【问题描述】:

我想在使用 SQL Server 比较查询中的字符串时忽略大小写。到目前为止,我可以使用这样的方法来做到这一点:

SELECT *
FROM Venue
WHERE
   Name COLLATE Latin1_general_CI_AI Like '%cafe%' COLLATE Latin1_general_CI_AI

有没有办法设置一个全局指令以影响每个查询? 像这样的:

SET COLLATE Latin1_general_CI_AI;
SELECT *
    FROM Venue
    WHERE
       Name Like '%this%';
SELECT *
    FROM Venue
    WHERE
       Name Like '%that%';
...

谢谢!

【问题讨论】:

是否有不能将数据库的排序规则设置为不区分大小写选项的原因? (msdn.microsoft.com/en-us/library/ms175835(v=sql.110).aspx) 或者,您可以将表中各个列的排序规则设置为与数据库的排序规则不同。 How to set column collation 不幸的是,用户想要选择是否要在每次查询之前忽略大小写。 相关问题:***.com/questions/7210189/… 如果您无权更改排序规则,我发现最简单的方法是使用 UPPER 或 LOWER 函数来比较数据。我以前使用过区分大小写的数据库。我理解你的痛苦! 【参考方案1】:

有没有办法设置一个全局指令以影响每个查询?

没有。

排序规则不是应用于查询的会话属性,它不能动态更改。

这个请求的另一个问题是区分大小写不是一个可以自行启用或禁用的选项:它是排序规则的属性,就像重音敏感、宽度敏感、特定字母的顺序一样排列在等。一个查询可以比较多个字段,每个字段都有不同的排序规则。因此,即使您可以设置一个对会话有效的排序规则,这也可能会强制其他排序规则的列在不要求区分大小写的情况下即时转换排序规则。全局会话设置也会影响排序(即 TOP(n)、ORDER BY 等),而不仅仅是比较。

由于问题是用户想要确定每次执行是否忽略部分排序规则,因此有几个选项,但都会导致一些性能损失:

    在动态 SQL 中构造查询(或多个查询):

    DECLARE @SQL NVARCHAR(MAX),
            @Collation NVARCHAR(50);
    
    SET @Collation = '';
    IF (@CaseInsensitive = 1)
    BEGIN
      SET @Collation = N'COLLATE Latin1_general_CI_AI';
    END;
    
    SET @SQL = N'SELECT *
      FROM Venue
      WHERE Name ' + @Collation + N' LIKE ''%' + @SearchParam
                   + N'%'' ' + @Collation;
    
    EXEC(@SQL);
    

    将每个字符转换为单个字符范围内的大写和小写对。这可以在应用层中针对正在搜索的参数值完成:

    默认区分大小写(不要做任何事情): @SearchParam = '这个' 不区分大小写: @SearchParam = '[tT][hH][iI][sS]'

    将所有内容强制为相同的情况。假设不区分大小写的选项是传入的附加参数:

    SELECT *
    FROM Venue
    WHERE CASE @CaseInsensitive
            WHEN 1 THEN LOWER(Name)
            ELSE Name
          END
             LIKE 
          CASE @CaseInsensitive
            WHEN 1 THEN '%' + LOWER(@SearchParam) + '%'
            ELSE '%' + @SearchParam + '%'
          END;
    

    或者,在查询之前执行LOWER()

    IF (@CaseInsensitive = 1)
    BEGIN
      SET @SearchParam = LOWER(@SearchParam);
    END;
    
    SELECT *
    FROM Venue
    WHERE CASE @CaseInsensitive
            WHEN 1 THEN LOWER(Name)
            ELSE Name
          END
             LIKE '%' + @SearchParam + '%';
    

【讨论】:

我会使用第三种变体。并将@SearchParam 的处理移到查询本身之外。只是为了让它更干净一点。 @VladimirBaranov 是的,我考虑过在应用程序层中提到 @SearchParam 可以“降低”,但对于要求对查询的调用者/实施者有这么大的信心并不太满意;-)。但是,它仍然是一个需要考虑的选项,所以我确实将它添加到 #3 以及我对这种方法的担忧。此外,由于#3 中的 CASE 语句存在潜在的查询优化器问题,我更喜欢选项 #2,但正确的性能测试应该是决定因素:-)。 其实我想在存储过程开始的时候在服务器上计算LOWER(@SearchParam)。在应用程序中执行此操作可能是不正确的(至少理论上,如果应用程序使用的排序规则与服务器使用的排序规则不完全相同,那么应用程序中 ToLower 的结果可能与服务器中的 LOWER 不同) .当您执行LIKE '%something%' 时,性能无论如何都会很糟糕。 @VladimirBaranov Duh,这更有意义;-)。我又更新了。

以上是关于SQL Server 不区分大小写的查询的主要内容,如果未能解决你的问题,请参考以下文章

通过 C# 查询时 SQL Server 2005 区分大小写

SQL Server 检查是不是区分大小写?

SQL Server:为啥不区分大小写的列上的 SELECT 比区分大小写的列更快?

sql server数据库表中各字段名需要大写吗

sql语句查询字母字段时不区分大小写

SQL Server 的 LIKE 运算符是不是区分大小写?