Vấn đề:
Nguyên nhân:Cột 'Tên' không phân biệt chữ hoa chữ thường (CI
) đối chiếu.
Giải pháp:Bạn phải sử dụng CS
đối chiếu:SELECT * FROM fn_helpcollations() WHERE description LIKE N'%case-sensitive%'
.
Lưu ý:Có một đối chiếu cơ sở dữ liệu và đối chiếu mức cột. Và, cũng có, đối chiếu cấp máy chủ.
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
*/
Chỉ cần thay đổi đối chiếu cơ sở dữ liệu sẽ KHÔNG thay đổi đối chiếu cho các bảng và cột người dùng hiện có:
Sau khi thay đổi đối chiếu cơ sở dữ liệu , đầu ra của các truy vấn trên sẽ là:
/*
DatabaseCollation -- changed
----------------------------
SQL_Latin1_General_CP1_CS_AS
*/
/*
ColumnCollation -- no change
----------------------------
SQL_Latin1_General_CP1_CI_AS
*/
và, như bạn có thể thấy sự đối chiếu của cột Name
vẫn là CI.
Hơn nữa, việc thay đổi đối chiếu cơ sở dữ liệu sẽ chỉ ảnh hưởng đến các bảng và cột được tạo mới. Do đó, việc thay đổi đối chiếu cơ sở dữ liệu có thể tạo ra các kết quả lạ (theo ý kiến của tôi ) vì một số [N][VAR]CHAR
các cột sẽ là CI và các cột mới sẽ là CS.
Giải pháp chi tiết # 1:nếu chỉ là một số truy vấn cho cột Name
cần phải là CS
sau đó tôi sẽ viết lại WHERE
do đó, mệnh đề của các truy vấn này:
SELECT Name
FROM dbo.Table_2
WHERE Name LIKE 'Joe' AND Name LIKE 'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS
Điều này sẽ cung cấp một thay đổi đối với SQL Server để thực hiện Index Seek
trên cột Name
(trong đó có một chỉ mục trên cột Name
). Ngoài ra, kế hoạch thực thi sẽ bao gồm một chuyển đổi ngầm định (xem Predicate
thuộc tính cho Index Seek
) vì vị từ sau Name = N'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS
.
Giải pháp chi tiết # 2:nếu tất cả các truy vấn cho cột Name
cần phải là CS thì tôi sẽ chỉ thay đổi đối chiếu cho cột Name
do đó:
-- 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'