【发布时间】:2010-11-16 11:57:44
【问题描述】:
如何构造 SQL 查询(MS SQL Server),其中“where”子句不区分大小写?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
我希望结果返回忽略此案
【问题讨论】:
标签: sql sql-server where-clause case-insensitive
如何构造 SQL 查询(MS SQL Server),其中“where”子句不区分大小写?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
我希望结果返回忽略此案
【问题讨论】:
标签: sql sql-server where-clause case-insensitive
你在哪个数据库上?对于 MS SQL Server,它是一个数据库范围的设置,或者您可以使用 COLLATE 关键字在每个查询中覆盖它。
【讨论】:
在 SQL Server 数据库的默认配置中,字符串比较是不区分大小写的。如果您的数据库覆盖了此设置(通过使用备用排序规则),那么您需要指定在查询中使用哪种排序规则。
SELECT * FROM myTable WHERE myField = 'sOmeVal' COLLATE SQL_Latin1_General_CP1_CI_AS
请注意,我提供的排序规则只是一个示例(尽管它很可能对您来说很好用)。可以在here 找到更详尽的 SQL Server 排序规则大纲。
【讨论】:
WHERE语句的末尾,会影响所有WHERE子句,对吗?
UPPER 或LOWER 大小写,然后使用LIKE 进行搜索?
通常,字符串比较不区分大小写。如果您的数据库配置为区分大小写的排序规则,则需要强制使用不区分大小写的排序规则:
SELECT balance FROM people WHERE email = 'billg@microsoft.com'
COLLATE SQL_Latin1_General_CP1_CI_AS
【讨论】:
你可以强制区分大小写,像这样强制转换为 varbinary:
SELECT * FROM myTable
WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
【讨论】:
我在别处找到了另一个解决方案;也就是使用
upper(@yourString)
但是这里的每个人都在说,在 SQL Server 中,这并不重要,因为它无论如何都会忽略大小写?我很确定我们的数据库是区分大小写的。
【讨论】:
不,只使用LIKE 是行不通的。 LIKE 搜索与给定模式完全匹配的值。在这种情况下,LIKE 只会找到文本 'sOmeVal' 而不是 'someval'。
一个可行的解决方案是使用LCASE() 函数。 LCASE('sOmeVal') 获取文本的小写字符串:'someval'。如果你在比较的两边都使用这个函数,它会起作用:
SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')
该语句比较两个小写字符串,因此您的“sOmeVal”将匹配“someval”的所有其他表示法(例如“Someval”、“sOMEVAl”等)。
【讨论】:
LCASE()(至少我看不到)。我认为这个答案适用于完全不同的 RDBMS。有关字符串比较的说明,请参阅my answer。
前 2 个答案(来自 Adam Robinson 和 Andrejs 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 点。
其他四个答案都有不同程度的错误。
我将在这里澄清所有误解,以便读者可以做出最合适/最有效的选择。
不要使用UPPER()。这完全是不必要的额外工作。使用COLLATE 子句。无论哪种情况都需要进行字符串比较,但使用UPPER() 还必须逐个字符检查是否存在大写映射,然后更改它。你需要在双方都这样做。添加COLLATE 只是指示处理使用与默认设置不同的规则集生成排序键。使用COLLATE 肯定比使用UPPER() 更有效(或“性能”,如果你喜欢这个词:),正如test script (on PasteBin) 所证明的那样。
还有noted by @Ceisc on @Danny's answer:的问题
在某些语言中,转换不会往返。即 LOWER(x) != LOWER(UPPER(x))。
土耳其语大写“İ”是常见的例子。
不,排序规则不是数据库范围的设置,至少在这种情况下不是。有一个数据库级别的默认排序规则,它被用作未指定 COLLATE 子句的更改和新创建的列的默认值(这可能是这种常见误解的来源),但它不会直接影响查询除非您将字符串文字和变量与其他字符串文字和变量进行比较,或者您正在引用数据库级元数据。
不,排序不是每个查询。
排序规则是每个谓词(即某操作数某事)或表达式,而不是每个查询。整个查询都是如此,而不仅仅是WHERE 子句。这包括 JOIN、GROUP BY、ORDER BY、PARTITION BY 等。
不,请勿转换为VARBINARY(例如convert(varbinary, myField) = convert(varbinary, 'sOmeVal')),原因如下:
_BIN2 结尾的一个,否则您别无选择,只能使用以 _BIN 结尾的一个。如果数据是NVARCHAR,那么您使用哪个区域设置都没有关系,因为在这种情况下它们都是相同的,因此Latin1_General_100_BIN2 总是有效的。如果数据是VARCHAR,则必须使用数据当前所在的相同区域设置(例如Latin1_General、French、Japanese_XJIS 等),因为区域设置决定了使用的代码页,并且更改代码页面可以更改数据(即数据丢失)。CONVERT() 一起使用时,它将使用 30 默认值。危险在于,如果字符串可能超过 30 个字节,它将被静默截断,并且您可能会从该谓词中得到不正确的结果。不,LIKE 并不总是区分大小写。它使用被引用列的排序规则,或者如果将变量与字符串文字进行比较,则使用数据库的排序规则,或者通过可选的COLLATE 子句指定的排序规则。
LCASE 不是 SQL Server 函数。它似乎是 Oracle 或 MySQL。或者可能是 Visual Basic?
由于问题的上下文是将列与字符串文字进行比较,因此实例的排序规则(通常称为“服务器”)和数据库的排序规则都没有任何直接 em> 影响这里。排序规则按每列存储,每列可以有不同的排序规则,这些排序规则不需要与数据库的默认排序规则或实例的排序规则相同。当然,如果在创建数据库时未指定 COLLATE 子句,则实例排序规则是新创建的数据库将用作其默认排序规则的默认设置。同样,如果未指定 COLLATE 子句,数据库的默认排序规则是更改或新创建的列将使用的排序规则。
您应该使用与列的排序规则相同的不区分大小写的排序规则。使用以下查询查找列的排序规则(更改表的名称和架构名称):
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
【讨论】: