Ignorar acentos en 'donde'

17

En nuestra base de datos tenemos múltiples entradas con caron / hatschek. Ahora nuestros usuarios quieren encontrar entradas que incluyan caron / hatschek cuando buscan entradas sin ellas. Lo mostraré con un simple ejemplo:

En nuestra base de datos tenemos la entrada (contacto con nombre)

Millière

entonces este nombre es correcto en el país donde vive la persona.

En nuestro país no tenemos ningún personaje con caron / hatschek, por lo tanto, nuestro usuario busca Milliere. No aparecen resultados, ya èque obviamente no coincide e.

No tengo idea de cómo esto podría ser realizado como é, è, êy muchos más están disponibles (y esto es sólo un ejemplo de carta e...).

(La otra forma sería mucho más fácil, ya que podría simplemente reemplazar todas las letras con caron / hatschek por la básica. Obviamente, nuestros usuarios quieren la versión correcta del nombre en la base de datos, no la lisiada).

lumo
fuente
Tenga en cuenta que la letra "è" no tiene caron / hacek, tiene un acento grave; un caron / hacek sería "ě". ¿Te refieres a "personajes con acentos" o algo así? ¿O te refieres específicamente al acento caron / hacek?
psmears
Me refiero a cualquier personaje con "signos" (lo siento, no sé el nombre real para él.
lumo

Respuestas:

31

Este problema puede resolverse utilizando colaciones insensibles al acento .

Es probable que su base de datos esté utilizando una clasificación AS (sensible al acento), por lo que, de forma predeterminada, buscará la coincidencia exacta, incluidos los acentos.

Puede indicar a la cláusula WHERE que use otra clasificación que no sea la predeterminada de la base de datos especificando una clasificación con la comparación.

En este dbfiddle , creé un ejemplo usando las intercalaciones LATIN1, pero podría usar el mismo enfoque con la intercalación que está utilizando simplemente cambiando AS a AI para la intercalación que su columna está utilizando actualmente.

Utilice la clasificación Accent Insensitive que coincida con la clasificación que está utilizando el columnmn. Por ejemplo, si la columna está usando SQL_Latin1_General_CP1_CI_AS, use SQL_Latin1_General_CP1_CI_AIy not Latin1_General_CI_ASo Latin1_General_100_CI_AScualquiera de las variaciones de esos dos, ya que el comportamiento de las colaciones no SQL_ diferirá en más formas que solo la insensibilidad al acento, y eso podría no ser esperado por los usuarios.

Puede consultar la clasificación actual en 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

Lea a través del uso de intercalaciones de SQL Server para obtener más información.

Por otra parte, es probable que desee ordenar para utilizar esta intercalación (como peufeu señaló en los comentarios) para asegurarse de que "é" se clasifique con "e". De lo contrario, alguien que pagina los resultados en orden alfabético se sorprendería de no encontrar la "é" donde espera que estén, pero si solo desea tocar esta consulta, también puede agregar la COLLATEcláusula ORDER BY.

Como señaló Solomon Rutzky en los comentarios, si esto solo afecta a 1 o unas pocas columnas, otra opción es crear una columna computada no persistente que simplemente repita la columna "nombre" y proporcione la colación insensible al acento, y luego indexe el cómputo calculado columna. Esto evita el escaneo causado al cambiar la intercalación dentro de la consulta. Entonces la consulta necesita filtrarse en la nueva columna.

Algo como:

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

O también podría crear una vista en lugar de agregar una columna calculada (como lo prefiere jyao ).

Tom V - Equipo Mónica
fuente
1
Tom: Quisiera señalar (y destacar) que deberían usar la versión Accent-Insensitive de la Clasificación que está utilizando la columna (la clasificación predeterminada de la base de datos, mencionada en el párrafo 3, no es relevante para esta pregunta). Si la columna está usando SQL_Latin1_General_CP1_CI_AS, use SQL_Latin1_General_CP1_CI_AIy not Latin1_General_CI_ASo Latin1_General_100_CI_AScualquiera de las variaciones de esos dos, ya que el comportamiento de las no SQL_colaciones diferirá en más formas que solo la insensibilidad al acento, y eso podría no ser esperado por los usuarios. La colación se encuentra en sys.columns.
Solomon Rutzky
@SolomonRutzky buena sugerencia
Tom V - Equipo Mónica