【问题标题】:SQL server ignore case in a where expressionSQL Server 忽略 where 表达式中的大小写
【发布时间】:2010-11-16 11:57:44
【问题描述】:

如何构造 SQL 查询(MS SQL Server),其中“where”子句不区分大小写?

SELECT * FROM myTable WHERE myField = 'sOmeVal'

我希望结果返回忽略此案

【问题讨论】:

    标签: sql sql-server where-clause case-insensitive


    【解决方案1】:

    你在哪个数据库上?对于 MS SQL Server,它是一个数据库范围的设置,或者您可以使用 COLLATE 关键字在每个查询中覆盖它。

    【讨论】:

    • 您好。对于 SQL Server,就这个问题的意义而言,它既不是数据库范围的设置,也不是每个查询。详情请见my answer
    【解决方案2】:

    在 SQL Server 数据库的默认配置中,字符串比较不区分大小写的。如果您的数据库覆盖了此设置(通过使用备用排序规则),那么您需要指定在查询中使用哪种排序规则。

    SELECT * FROM myTable WHERE myField = 'sOmeVal' COLLATE SQL_Latin1_General_CP1_CI_AS
    

    请注意,我提供的排序规则只是一个示例(尽管它很可能对您来说很好用)。可以在here 找到更详尽的 SQL Server 排序规则大纲。

    【讨论】:

    • 确认一下,这个只需要添加一次,在WHERE语句的末尾,会影响所有WHERE子句,对吗?
    • 想知道您的答案是否存在性能问题,方法是将列值转换为UPPERLOWER 大小写,然后使用LIKE 进行搜索?
    • @ashleedawg - 好问题.. 它似乎是每行设置。
    【解决方案3】:

    通常,字符串比较不区分大小写。如果您的数据库配置为区分大小写的排序规则,则需要强制使用不区分大小写的排序规则:

    SELECT balance FROM people WHERE email = 'billg@microsoft.com'
      COLLATE SQL_Latin1_General_CP1_CI_AS 
    

    【讨论】:

    • @AskeB。 Andrejs:这在技术上不是数据库配置问题。有关字符串比较的说明,请参阅my answer
    【解决方案4】:

    你可以强制区分大小写,像这样强制转换为 varbinary:

    SELECT * FROM myTable 
    WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
    

    【讨论】:

    • 虽然这很有效,但它不是一个可取的方法。排序规则用于管理排序和字符串比较。
    • @AdamRobinson 这不是关于“字符串比较”吗?
    • @Fandango68 是的,是的,Adam 说在进行字符串比较时排序规则更好。
    【解决方案5】:

    我在别处找到了另一个解决方案;也就是使用

    upper(@yourString)
    

    但是这里的每个人都在说,在 SQL Server 中,这并不重要,因为它无论如何都会忽略大小写?我很确定我们的数据库是区分大小写的。

    【讨论】:

    • 你说得对,数据库可以区分大小写,但这是非常低效的,即使需要它也是如此。 COLLATE 是要使用的关键字。
    • 感谢您提出这个问题,@mjaggard。我希望您或任何似乎对我的答案投反对票的人,为像我这样搜索并找到像我这样的答案的人的利益而详细说明。
    • 赞成这个,因为它是一个完全合理的解释。 Collat​​e 会产生过多的开销,如果您的字符串中包含排序规则无法理解的字符怎么办?拉丁语 1 是一种糟糕的编码方案。如果您的字符串中有撇号(例如:O'Brien),那么祝您获得有意义的结果。
    • 也赞成。我可以想到很多这样有用的情况。此外,做某事的好方法通常不止一种。
    • 为了比较而改变字符串的大小写通常是不好的。在某些语言中,情况转换不会往返。即 LOWER(x) != LOWER(UPPER(x))。
    【解决方案6】:

    不,只使用LIKE 是行不通的。 LIKE 搜索与给定模式完全匹配的值。在这种情况下,LIKE 只会找到文本 'sOmeVal' 而不是 'someval'。

    一个可行的解决方案是使用LCASE() 函数。 LCASE('sOmeVal') 获取文本的小写字符串:'someval'。如果你在比较的两边都使用这个函数,它会起作用:

    SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')

    该语句比较两个小写字符串,因此您的“sOmeVal”将匹配“someval”的所有其他表示法(例如“Someval”、“sOMEVAl”等)。

    【讨论】:

    • 在 99.9% 的 _CI 排序的 SQL Server 安装中,LIKE 不区分大小写。
    • 现在这个函数被称为 LOWER
    • @DavidBrossard 和 David Hermanns,我认为 SQL Server 中从来没有 LCASE()(至少我看不到)。我认为这个答案适用于完全不同的 RDBMS。有关字符串比较的说明,请参阅my answer
    【解决方案7】:

    前 2 个答案(来自 Adam RobinsonAndrejs Cainikovs)有点正确,因为它们在技术上确实有效,但它们的解释是错误的,因此在许多情况下可能会产生误导。例如,虽然SQL_Latin1_General_CP1_CI_AS 排序规则在许多情况下都可以使用,但不应假定它是适当的不区分大小写的排序规则。事实上,鉴于 OP 正在使用区分大小写(或可能是二进制)排序规则的数据库中工作,我们知道 OP 没有使用许多安装(尤其是安装在操作系统上的任何安装)默认的排序规则使用美国英语作为语言):SQL_Latin1_General_CP1_CI_AS。当然,OP 可以使用SQL_Latin1_General_CP1_CS_AS,但是在使用VARCHAR 数据时,不要更改代码页很重要,因为它可能会导致数据丢失,这由排序规则的语言环境/文化(即 Latin1_General 与法语与希伯来语等)。请参阅下面的第 9 点。

    其他四个答案都有不同程度的错误。

    我将在这里澄清所有误解,以便读者可以做出最合适/最有效的选择。

    1. 不要使用UPPER()。这完全是不必要的额外工作。使用COLLATE 子句。无论哪种情况都需要进行字符串比较,但使用UPPER() 还必须逐个字符检查是否存在大写映射,然后更改它。你需要在双方都这样做。添加COLLATE 只是指示处理使用与默认设置不同的规则集生成排序键。使用COLLATE 肯定比使用UPPER() 更有效(或“性能”,如果你喜欢这个词:),正如test script (on PasteBin) 所证明的那样。

      还有noted by @Ceisc on @Danny's answer:的问题

      在某些语言中,转换不会往返。即 LOWER(x) != LOWER(UPPER(x))。

      土耳其语大写“İ”是常见的例子。

    2. 不,排序规则不是数据库范围的设置,至少在这种情况下不是。有一个数据库级别的默认排序规则,它被用作未指定 COLLATE 子句的更改和新创建的列的默认值(这可能是这种常见误解的来源),但它不会直接影响查询除非您将字符串文字和变量与其他字符串文字和变量进行比较,或者您正在引用数据库级元数据。

    3. 不,排序不是每个查询。

    4. 排序规则是每个谓词(即某操作数某事)或表达式,而不是每个查询。整个查询都是如此,而不仅仅是WHERE 子句。这包括 JOIN、GROUP BY、ORDER BY、PARTITION BY 等。

    5. 不,请勿转换为VARBINARY(例如convert(varbinary, myField) = convert(varbinary, 'sOmeVal')),原因如下:

      1. 这是一个二进制比较,不区分大小写(这是本问题所要求的)
      2. 如果您确实需要二进制比较,请使用二进制排序规则。如果您使用的是 SQL Server 2008 或更高版本,请使用以 _BIN2 结尾的一个,否则您别无选择,只能使用以 _BIN 结尾的一个。如果数据是NVARCHAR,那么您使用哪个区域设置都没有关系,因为在这种情况下它们都是相同的,因此Latin1_General_100_BIN2 总是有效的。如果数据是VARCHAR,则必须使用数据当前所在的相同区域设置(例如Latin1_GeneralFrenchJapanese_XJIS 等),因为区域设置决定了使用的代码页,并且更改代码页面可以更改数据(即数据丢失)。
      3. 在不指定大小的情况下使用可变长度数据类型将依赖于默认大小,并且有两种不同的默认值,具体取决于使用数据类型的上下文。对于字符串类型,它是 1 或 30。当与CONVERT() 一起使用时,它将使用 30 默认值。危险在于,如果字符串可能超过 30 个字节,它将被静默截断,并且您可能会从该谓词中得到不正确的结果。
      4. 即使您想要区分大小写的比较,binary collations are not case-sensitive(另一个非常常见的误解)。
    6. 不,LIKE 并不总是区分大小写。它使用被引用列的排序规则,或者如果将变量与字符串文字进行比较,则使用数据库的排序规则,或者通过可选的COLLATE 子句指定的排序规则。

    7. LCASE 不是 SQL Server 函数。它似乎是 Oracle 或 MySQL。或者可能是 Visual Basic?

    8. 由于问题的上下文是将列与字符串文字进行比较,因此实例的排序规则(通常称为“服务器”)和数据库的排序规则都没有任何直接 em> 影响这里。排序规则按每列存储,每列可以有不同的排序规则,这些排序规则不需要与数据库的默认排序规则或实例的排序规则相同。当然,如果在创建数据库时未指定 COLLATE 子句,则实例排序规则是新创建的数据库将用作其默认排序规则的默认设置。同样,如果未指定 COLLATE 子句,数据库的默认排序规则是更改或新创建的列将使用的排序规则。

    9. 您应该使用与列的排序规则相同的不区分大小写的排序规则。使用以下查询查找列的排序规则(更改表的名称和架构名称):

      SELECT col.*
      FROM   sys.columns col
      WHERE  col.[object_id] = OBJECT_ID(N'dbo.TableName')
      AND    col.[collation_name] IS NOT NULL;
      

      然后只需将_CS 更改为_CI。因此,Latin1_General_100_CS_AS 将变为 Latin1_General_100_CI_AS

      如果该列使用二进制排序规则(以 _BIN_BIN2 结尾),则使用以下查询查找类似排序规则:

      SELECT *
      FROM   sys.fn_helpcollations() col
      WHERE  col.[name] LIKE N'{CurrentCollationMinus"_BIN"}[_]CI[_]%';
      

      例如,假设列使用Japanese_XJIS_100_BIN2,请执行以下操作:

      SELECT *
      FROM   sys.fn_helpcollations() col
      WHERE  col.[name] LIKE N'Japanese_XJIS_100[_]CI[_]%';
      

    有关排序规则、编码等的更多信息,请访问:Collations Info

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多