Ignoruj ​​akcenty w „gdzie”

17

W naszej bazie danych mamy wiele wpisów z caron / hatschek. Teraz nasi użytkownicy chcą znaleźć wpisy, w tym caron / hatschek, gdy szukają wpisów bez. Pokażę to na prostym przykładzie:

W naszej bazie danych mamy wpis (kontakt z imieniem)

Millière

więc ta nazwa jest poprawna w kraju, w którym mieszka osoba.

W naszym kraju nie mamy żadnych znaków z caron / hatschek, dlatego nasz użytkownik szuka Milliere. Nie pojawiają się żadne wyniki, ponieważ èoczywiście nie pasują e.

Nie mam pojęcia, jak to może być realizowane jako é, è, êi wiele innych dostępne są (i to tylko przykład na literę e...).

(Drugi sposób byłby znacznie łatwiejszy, ponieważ mogłem po prostu zastąpić wszystkie litery caron / hatschek podstawową. Oczywiście, nasi użytkownicy chcą poprawnej wersji nazwy w bazie danych, a nie kalekiej).

lumo
źródło
Zauważ, że litera „è” nie ma caron / hacek, ma poważny akcent; caron / hacek to „ě”. Masz na myśli „postacie z akcentami” czy coś takiego? A może masz na myśli akcent caron / hacek?
psmears
mam na myśli dowolne znaki z „znakami” (przepraszam, nie znam rzeczywistej nazwy.
lumo,

Odpowiedzi:

31

Ten problem można rozwiązać za pomocą sortowania niewrażliwego na akcenty .

Twoja baza danych prawdopodobnie używa sortowania AS (Accent Sensitive), więc domyślnie będzie wyszukiwać dokładne dopasowanie z uwzględnieniem akcentów.

Możesz poinstruować klauzulę WHERE, aby używała innego sortowania niż domyślna baza danych, określając sortowanie z porównaniem.

W tym pliku dbfiddle stworzyłem przykład przy użyciu zestawień LATIN1, ale możesz zastosować to samo podejście z zestawieniem, którego używasz, po prostu zmieniając AS w AI dla zestawienia, którego obecnie używa kolumna.

Użyj sortowania niewrażliwego na akcent, który pasuje do zestawienia używanego przez kolumnę. Na przykład, jeśli kolumna korzysta SQL_Latin1_General_CP1_CI_AS, używania SQL_Latin1_General_CP1_CI_AIi nie Latin1_General_CI_ASlub Latin1_General_100_CI_ASczy którykolwiek z tych dwóch wariantów od czasu zachowania się sortowania non-SQL_ będą różnić się na więcej sposobów niż tylko akcent niewrażliwości, i że nie można oczekiwać od użytkowników.

Możesz sprawdzić bieżące sortowanie w 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

Przeczytaj, używając SQL Server Collations, aby uzyskać więcej informacji.

Z drugiej strony prawdopodobnie chciałbyś, aby sortowanie używało tego sortowania (jak zauważył peufeu w komentarzach), aby mieć pewność, że „é” będzie sortowane za pomocą „e”. W przeciwnym razie ktoś, kto paginuje wyniki w kolejności alfabetycznej, byłby zaskoczony, gdyby nie znalazł „é” tam, gdzie się spodziewa, ale jeśli chcesz tylko dotknąć tego zapytania, możesz również dodać COLLATEklauzulę ORDER BY.

Jak zauważył Solomon Rutzky w komentarzach, jeśli dotyczy to tylko jednej lub kilku kolumn, inną opcją jest utworzenie nietrwałej kolumny obliczeniowej, która po prostu powtarza kolumnę „nazwa” i zapewnia sortowanie niewrażliwe na akcent, a następnie indeksuje obliczoną kolumna. Pozwala to uniknąć skanowania spowodowanego zmianą sortowania w zapytaniu. Następnie zapytanie musi zostać przefiltrowane według nowej kolumny.

Coś jak:

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);

Możesz też utworzyć widok zamiast dodawać kolumnę obliczeniową (tak jak preferuje jyao ).

Tom V - Team Monica
źródło
1
TOM: Chciałbym zauważyć (i podkreślić), że powinni używać wersji Collation Accent-Insensitive, z której korzysta kolumna (domyślne zestawienie bazy danych, o którym mowa w ust. 3, nie ma związku z tym pytaniem). Jeśli kolumna używa SQL_Latin1_General_CP1_CI_AS, użyj SQL_Latin1_General_CP1_CI_AIi nie, Latin1_General_CI_ASlub Latin1_General_100_CI_ASdowolna odmiana tych dwóch, ponieważ zachowanie braku SQL_sortowania będzie się różnić na więcej sposobów niż tylko niewrażliwość na akcent, a użytkownicy nie mogą się tego spodziewać. Sortowanie znajduje się w sys.columns.
Solomon Rutzky,
@SolomonRutzky dobra sugestia
Tom V - Team Monica