101

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

SELECT * FROM myTable WHERE myField = 'sOmeVal'

我希望结果回来忽略此案

4

7 回答 7

148

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

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

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

于 2009-08-03T20:16:38.157 回答
30

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

SELECT balance FROM people WHERE email = 'billg@microsoft.com'
  COLLATE SQL_Latin1_General_CP1_CI_AS 
于 2009-08-03T20:17:10.090 回答
25

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

upper(@yourString)

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

于 2010-07-16T01:11:46.920 回答
23

前 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从句。在这两种情况下都需要进行字符串比较,但 usingUPPER()还必须逐个字符检查是否存在大写映射,然后更改它。你需要在双方都这样做。添加COLLATE只是指示处理使用与默认情况下不同的规则集生成排序键。usingCOLLATE绝对比 using 更有效(或“性能”,如果您喜欢这个词 :) ,正如此测试脚本(在 PasteBin 上)UPPER()中所证明的那样。

    @Ceisc 在@Danny 的回答中也提到了这个问题:

    在某些语言中,情况转换不会往返。即 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. 如果您确实需要二进制比较,请使用二进制排序规则。_BIN2如果您使用的是 SQL Server 2008 或更高版本,请使用以_BIN. 如果数据是NVARCHAR,那么您使用哪种语言环境并不重要,因为在这种情况下它们都是相同的,因此Latin1_General_100_BIN2总是有效的。如果数据是VARCHAR,您必须使用数据当前所在的相同语言环境(例如Latin1_GeneralFrenchJapanese_XJIS等),因为语言环境决定了所使用的代码页,而更改代码页会改变数据(即数据丢失)。
    3. 在不指定大小的情况下使用可变长度数据类型将依赖于默认大小,并且有两种不同的默认值,具体取决于使用数据类型的上下文。对于字符串类型,它是 1 或 30。与CONVERT()它一起使用时将使用 30 默认值。危险是,如果字符串可能超过 30 个字节,它将被静默截断,并且您可能会从该谓词中得到不正确的结果。
    4. 即使您想要区分大小写的比较,二进制排序规则也不区分大小写(另一个非常常见的误解)。
  6. 不,LIKE并不总是区分大小写。它使用被引用列的排序规则,或者如果将变量与字符串文字进行比较,则使用数据库的排序规则,或者通过可选COLLATE子句指定的排序规则。

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

  8. 由于问题的上下文是将列与字符串文字进行比较,因此实例的排序规则(通常称为“服务器”)和数据库的排序规则在这里都没有任何直接影响。排序规则按每列存储,每列可以有不同的排序规则,这些排序规则不需要与数据库的默认排序规则或实例的排序规则相同。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.

    如果该列使用二进制排序规则(以_BINor结尾_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[_]%';
    

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

于 2019-01-29T23:40:55.107 回答
7

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

一个可行的解决方案是使用该LCASE()功能。LCASE('sOmeVal')获取文本的小写字符串:'someval'。如果您将此函数用于比较的双方,它会起作用:

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

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

于 2012-10-02T07:59:13.817 回答
4

您可以强制区分大小写,强制转换为 varbinary,如下所示:

SELECT * FROM myTable 
WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
于 2009-08-03T20:21:24.637 回答
2

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

于 2009-08-03T20:15:26.570 回答