Bỏ qua các dấu trong 'where'


17

Trong cơ sở dữ liệu của chúng tôi, chúng tôi có nhiều mục với caron / Hatschek. Bây giờ người dùng của chúng tôi muốn tìm các mục bao gồm caron / Hatschek khi họ tìm kiếm các mục mà không có. Tôi sẽ chỉ ra điều này bằng một ví dụ đơn giản:

Trong cơ sở dữ liệu của chúng tôi, chúng tôi có mục (liên hệ với tên)

Millière

Vì vậy, tên này là chính xác ở đất nước mà người sống.

Ở nước chúng tôi, chúng tôi không có bất kỳ ký tự nào có caron / Hatschek, do đó người dùng của chúng tôi tìm kiếm Milliere. Không có kết quả đi lên, như èrõ ràng là không phù hợp e.

Tôi không có ý tưởng như thế nào điều này có thể được thực hiện như é, è, êvà nhiều hơn nữa có sẵn (và điều này chỉ là một ví dụ về lá thư e...).

(Cách khác sẽ dễ dàng hơn nhiều, vì tôi có thể chỉ cần thay thế tất cả các chữ cái bằng caron / Hatschek bằng chữ cơ bản. Rõ ràng, người dùng của chúng tôi muốn có phiên bản chính xác của tên trong cơ sở dữ liệu, chứ không phải phiên bản bị tê liệt.)


Lưu ý chữ "è" không có caron / hacek, nó có dấu trọng âm; một caron / hacek sẽ là "". Bạn có nghĩa là "nhân vật có dấu" hoặc một cái gì đó như thế? Hay bạn đặc biệt có nghĩa là giọng caron / hacek?
psmears

ý tôi là bất kỳ ký tự nào có "dấu hiệu" (xin lỗi tôi không biết tên thật của nó.
lumo

Câu trả lời:


31

Vấn đề này có thể được giải quyết bằng cách sử dụng các va chạm không nhạy .

Cơ sở dữ liệu của bạn có thể đang sử dụng đối chiếu AS (Accent Sensitive) vì vậy theo mặc định, nó sẽ tìm kiếm kết quả khớp chính xác bao gồm cả các dấu.

Bạn có thể hướng dẫn mệnh đề WHERE sử dụng đối chiếu khác ngoài mặc định cơ sở dữ liệu bằng cách chỉ định đối chiếu với so sánh.

Trong dbfiddle này, tôi đã tạo một ví dụ bằng cách sử dụng các đối chiếu LATIN1 nhưng bạn có thể sử dụng cùng một cách tiếp cận với đối chiếu mà bạn đang sử dụng bằng cách thay đổi AS thành AI cho đối chiếu mà cột của bạn hiện đang sử dụng.

Sử dụng đối chiếu không nhạy cảm Accent phù hợp với đối chiếu mà colummn đang sử dụng. Ví dụ: nếu cột đang sử dụng SQL_Latin1_General_CP1_CI_AS, sử dụng SQL_Latin1_General_CP1_CI_AIvà không Latin1_General_CI_AShoặc Latin1_General_100_CI_ASbất kỳ biến thể nào của hai biến thể đó vì hành vi của các đối chiếu không phải SQL_ sẽ khác nhau theo nhiều cách hơn là không nhạy cảm với giọng nói và điều đó có thể không được người dùng mong đợi.

Bạn có thể kiểm tra đối chiếu hiện tại trong sys.columns.

CREATE TABLE testaccent (name nvarchar(50));
GO
INSERT INTO testaccent (name) VALUES ('Millière') , ('Milliere');
GO
-- returns Miliere
SELECT * FROM testaccent WHERE name = 'Milliere';

-- returns both
SELECT * FROM testaccent WHERE name='Milliere' COLLATE Latin1_General_CI_AI

--only returns Miliere
SELECT * FROM testaccent WHERE name='Milliere' COLLATE Latin1_General_CI_AS

Đọc qua Sử dụng SQL Server Collations để biết thêm thông tin.

Sau đó, một lần nữa bạn có thể muốn sắp xếp để sử dụng đối chiếu này (như peufeu đã lưu ý trong các nhận xét) để đảm bảo rằng "é" sắp xếp với "e". Mặt khác, ai đó phân trang thông qua kết quả theo thứ tự bảng chữ cái sẽ ngạc nhiên khi không tìm thấy "é" nơi họ mong đợi, nhưng nếu bạn chỉ muốn chạm vào truy vấn này, bạn cũng có thể thêm COLLATEmệnh đề vào ORDER BY.

Như đã lưu ý bởi Solomon Rutzky trong các bình luận, nếu điều này chỉ ảnh hưởng đến 1 hoặc một vài cột, thì một tùy chọn khác là tạo một cột được tính không kiên trì, chỉ đơn giản lặp lại cột "tên" và cung cấp đối chiếu không nhạy, sau đó lập chỉ mục tính toán cột. Điều này tránh việc quét gây ra bằng cách thay đổi đối chiếu trong truy vấn. Sau đó, truy vấn cần lọc trên cột mới.

Cái gì đó như:

ALTER TABLE 
dbo.[table_name] ADD [SearchName] datatype_of_name_column 
AS ([Name] COLLATE LATIN1_GENERAL_100_CI_AI)); 

CREATE INDEX [IX_table_name_SearchName] 
ON dbo.[table_name] ([SearchName] ASC);

Hoặc bạn cũng có thể tạo chế độ xem thay vì thêm cột được tính toán (như jyao thích).


1
Tom: Tôi sẽ lưu ý (và nhấn mạnh) rằng họ nên sử dụng phiên bản Collent-Insensitive của Collation mà cột đang sử dụng (đối chiếu mặc định của cơ sở dữ liệu, được đề cập trong đoạn 3, không liên quan đến câu hỏi này). Nếu cột đang sử dụng SQL_Latin1_General_CP1_CI_AS, sử dụng SQL_Latin1_General_CP1_CI_AIvà không Latin1_General_CI_AShoặc Latin1_General_100_CI_ASbất kỳ biến thể nào của hai biến thể đó vì hành vi của các SQL_đối chiếu sẽ khác nhau theo nhiều cách hơn là không nhạy cảm với giọng nói và điều đó có thể không được người dùng mong đợi. Đối chiếu được tìm thấy trong sys.columns.
Solomon Rutzky

@SolomonRutzky đề nghị tốt
Tom V - Đội Monica
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.