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
为什么它不区分大小写?
问题:
查询不区分大小写
原因:列'名称'具有不区分大小写的(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)
