Ignorez les accents dans «où»

17

Dans notre base de données, nous avons plusieurs entrées avec caron / hatschek. Maintenant, nos utilisateurs veulent trouver des entrées, y compris caron / hatschek, lorsqu'ils recherchent des entrées sans. Je vais le montrer par un exemple simple:

Dans notre base de données, nous avons l'entrée (contact avec nom)

Millière

donc ce nom est correct dans le pays où la personne vit.

Dans notre pays, nous n'avons aucun personnage avec caron / hatschek, donc notre utilisateur recherche Milliere. Aucun résultat èn'apparaît , car cela ne correspond évidemment pas e.

Je ne sais pas comment cela pourrait être réalisé que é, è, êet beaucoup d' autres sont disponibles (ce qui est seulement un exemple pour la lettre e...).

(L'autre façon serait beaucoup plus facile, car je pourrais simplement remplacer toutes les lettres par caron / hatschek par la chaîne de base. Évidemment, nos utilisateurs veulent la bonne version du nom dans la base de données, pas celle qui est paralysée.)

lumo
la source
Notez que la lettre "è" n'a pas de caron / hacek, elle a un accent grave; un caron / hacek serait "ě". Voulez-vous dire "personnages avec des accents" ou quelque chose comme ça? Ou voulez-vous dire spécifiquement l'accent caron / hacek?
psmears
je veux dire tous les caractères avec des "signes" (désolé, je ne connais pas le nom réel de celui-ci.
lumo

Réponses:

31

Ce problème peut être résolu en utilisant des classements insensibles aux accents .

Votre base de données utilise probablement un classement AS (sensible aux accents). Par défaut, il recherchera la correspondance exacte, y compris les accents.

Vous pouvez demander à la clause WHERE d'utiliser un classement différent de celui par défaut de la base de données en spécifiant un classement avec la comparaison.

Dans ce dbfiddle, j'ai créé un exemple en utilisant les classements LATIN1, mais vous pouvez utiliser la même approche avec le classement que vous utilisez en changeant simplement AS en AI pour le classement que votre colonne utilise actuellement.

Utilisez le classement Accent Insensitive qui correspond au classement utilisé par la colonne. Par exemple, si la colonne utilise SQL_Latin1_General_CP1_CI_AS, utilise SQL_Latin1_General_CP1_CI_AIet non Latin1_General_CI_ASou l'une Latin1_General_100_CI_ASou l'autre des variantes de ces deux, car le comportement des classements non-SQL_ différera de bien des façons plus que la simple insensibilité à l'accent, et cela pourrait ne pas être attendu par les utilisateurs.

Vous pouvez archiver le classement actuel 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

Lisez la section Utilisation des classements SQL Server pour plus d'informations.

Là encore, vous voudrez probablement que le tri utilise ce classement (comme peufeu l'a noté dans les commentaires) pour s'assurer que "é" trie avec "e". Sinon, quelqu'un qui pagine dans les résultats par ordre alphabétique serait surpris de ne pas trouver le "é" où il s'attend à ce qu'ils soient, mais si vous voulez seulement toucher cette requête, vous pouvez également ajouter la COLLATEclause ORDER BY.

Comme l'a noté Solomon Rutzky dans les commentaires, si cela n'affecte qu'une ou plusieurs colonnes, une autre option consiste à créer une colonne calculée non persistante qui répète simplement la colonne "nom" et fournit le classement insensible à l'accent, puis indexe le calcul colonne. Cela évite l'analyse provoquée par la modification du classement dans la requête. Ensuite, la requête doit filtrer sur la nouvelle colonne.

Quelque chose comme:

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

Ou vous pouvez également créer une vue au lieu d'ajouter une colonne calculée (comme préfère jyao ).

Tom V - Équipe Monica
la source
1
Tom: Je voudrais noter (et souligner) qu'ils devraient utiliser la version insensible à l'accentuation du classement que la colonne utilise (le classement par défaut de la base de données, mentionné au paragraphe 3, n'est pas pertinent pour cette question). Si la colonne utilise SQL_Latin1_General_CP1_CI_AS, utilisez SQL_Latin1_General_CP1_CI_AIet non Latin1_General_CI_ASou l'une Latin1_General_100_CI_ASou l'autre des variantes de ces deux, car le comportement des non- SQL_classements différera de bien des façons plus que la simple insensibilité à l'accent, et cela pourrait ne pas être attendu par les utilisateurs. Le classement se trouve dans sys.columns.
Solomon Rutzky
@SolomonRutzky good suggestion
Tom V - Team Monica