SQL Server Like Query不区分大小写

2 sql sql-server sql-server-2008 sql-server-2008-r2 sql-server-2012

询问

SELECT  * 
from Table_2  
WHERE  name like ('Joe');
Run Code Online (Sandbox Code Playgroud)

产量

1   100 Joe
2   200 JOE
3   300 jOE
4   400 joe

为什么它不区分大小写?

Bog*_*ean 6

问题:

查询不区分大小写

原因:列'名称'具有不区分大小写的(CI)排序规则.

解决方案:您必须使用CS排序规则:SELECT * FROM fn_helpcollations() WHERE description LIKE N'%case-sensitive%'.

注意:存在数据库排序规则和列级排序规则.而且,还有一个服务器级别的排序规则.

SELECT  DATABASEPROPERTYEX(DB_NAME(), 'Collation') AS DatabaseCollation
/*
-- Sample output (my database)
DatabaseCollation
----------------------------
SQL_Latin1_General_CP1_CI_AS
*/

SELECT  col.collation_name AS ColumnCollation
FROM    sys.columns col
WHERE   col.object_id = OBJECT_ID(N'dbo.Table_2') 
AND     col.name = N'Name'
/*
-- Sample output (my database)
ColumnCollation
----------------------------
SQL_Latin1_General_CP1_CI_AS
*/
Run Code Online (Sandbox Code Playgroud)

简单地更改数据库排序规则不会更改现有用户表和列的排序规则:

此语句不会更改任何现有用户定义表中列的排序规则.可以使用ALTER TABLE的COLLATE子句更改这些内容.

资源

改变数据库归类,上述查询的输出将是:

/*
DatabaseCollation -- changed
----------------------------
SQL_Latin1_General_CP1_CS_AS
*/

/*
ColumnCollation -- no change
----------------------------
SQL_Latin1_General_CP1_CI_AS
*/
Run Code Online (Sandbox Code Playgroud)

并且,正如您所看到的,列的整理Name仍然是CI.

此外,更改数据库归类将仅影响新创建的表和列.因此,更改数据库归类可能会产生奇怪的结果(在我看来),因为某些[N][VAR]CHAR列将是CI,新列将是CS.

详细解决方案#1:如果只Name需要对列的一些查询,CS那么我将重写WHERE这些查询的子句:

SELECT  Name 
FROM    dbo.Table_2
WHERE   Name LIKE 'Joe' AND Name LIKE 'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

这将对SQL Server进行更改以执行Index Seekon on column Name(在列上有索引Name).此外,由于以下谓词,执行计划将包括隐式转换(请参阅Predicate属性Index Seek)Name = N'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS.

详细解决方案#2:如果列的所有查询都Name需要是CS,那么我将仅更改列的排序规则Name:

-- Drop all objects that depends on this column (ex. indexes, constraints, defaults)
DROP INDEX IX_Table_2_Name ON dbo.Table_2

-- Change column's collation
ALTER TABLE dbo.Table_2
ALTER COLUMN Name VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CS_AS
-- Replace VARCHAR(50) with proper data type and max. length
-- Replace COLLATE SQL_Latin1_General_CP1_CS_AS with the right CS collation

-- Recreate all objects that depends on column Name (ex. indexes, constraints, defaults)
CREATE INDEX IX_Table_2_Name ON dbo.Table_2 (Name)

-- Test query
SELECT  Name 
FROM    dbo.Table_2
WHERE   Name LIKE 'Joe'
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述