Tratar ciertos caracteres árabes como idénticos

10

En árabe tenemos caracteres como ا (alef) y أ (alef con hamza).

Los usuarios los escriben indistintamente y queremos buscarlos indistintamente. SQL Server los trata como caracteres separados. ¿Cómo puedo hacer que SQL los trate como el mismo personaje?

Pensé en reemplazar cualquier أ (alef con hamza) con ا (alef) en la inserción, pero tenemos muchas alternativas en idioma árabe, no solo ا (alef) y أ (alef con hamza).

Lo intenté Arabic_CI_ASy Arabic_CI_AIeso no resuelve el problema.

Aquí hay un script para regenerar el problema:

CREATE TABLE [dbo].[TestTable] (
    [ArabicChars] [nvarchar](50) NOT NULL,

    CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED 
    (
       [ArabicChars] ASC
    )
) ON [PRIMARY];


INSERT INTO TestTable values (N'احمد');
INSERT INTO TestTable values (N'أحمد');

SELECT * 
FROM TestTable 
WHERE ArabicChars like N'ا%';

El resultado es:

ArabicChars 

احمد

(1 row(s) affected)

El resultado deseado serían las dos filas que insertamos.

George Botros
fuente
No hay problema. Aaron Bertrand tiene un pequeño guión que puedes adaptar para probar todas las posibles colaciones. Sin embargo, sospecho que ninguna recopilación considerará esos dos caracteres iguales.
Nick Chammas
pero tiene dos caracteres diferentes en los nombres indicados, al menos en apariencia. Y, por supuesto, creo que deberían ser tratados como caracteres diferentesا and أ
nuux
3
@NickChammas como adivinó SOUNDEX () devuelve 0000 para cualquier personaje árabe
George Botros
1
@NickChammas: cuál es el problema entonces: el comportamiento del usuario + suposición difiere del comportamiento de clasificación más estricto.
gbn
1
@gbn: dado que estas son letras diferentes, diría que el problema es la educación del usuario. Si los usuarios quieren que esas cartas sean tratadas de manera equitativa, especialmente en una búsqueda, entonces esa funcionalidad debe construirse explícitamente. No es un problema de colación.
Nick Chammas

Respuestas:

4

Hice algunas pruebas y supongo que es una solución, pero puede hacer su trabajo, ya que SQL por sí mismo no está ayudando mucho.

si notas que los unicodes de estos personajes están cerca uno del otro

select unicode(N'أ')
  = 1571

select unicode(N'ا')
  = 1575

select unicode(N'إ')
  = 1573

así que entre أ y ا, es de 1571 a 1575 o si quieres asegurarte de tener todo en el medio

asegúrese de incluir de 1569 a 1575

cuales son

Select NCHAR(1569) = ء
Select NCHAR(1570) = آ
Select NCHAR(1571) = أ
Select NCHAR(1572) = ؤ
Select NCHAR(1573) = إ
Select NCHAR(1574) = ئ 
Select NCHAR(1575) = ا

Por lo tanto, para asegurarse de incluir todo lo similar en su búsqueda, puede usar expresiones regulares

SELECT * 
FROM TestTable 
WHERE ArabicChars like '%[ء-ا]%'

así que en este caso obtienes todos los caracteres entre ء y ا que incluyen todos aquellos entre 1569 y 1575

así que en este caso si tu mesa tiene

 CREATE TABLE [dbo].[TestTable]  (
    [ArabicChars] [nvarchar](50) COLLATE Arabic_CI_AI NOT NULL,
) 
INSERT INTO TestTable values (N'احمد');
INSERT INTO TestTable values (N'أحمد');
INSERT INTO TestTable values (N'إحمد');

la consulta anterior los obtendrá a todos.

pero notarás algo gracioso

si tiene su columna como clave principal

CREATE TABLE [dbo].[TestTable]  (
    [ArabicChars] [nvarchar](50) COLLATE Arabic_CI_AI NOT NULL,

    CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED 
    (
       [ArabicChars] ASC
    )
) ON [PRIMARY];

no podrá insertar estos 2 registros

INSERT INTO TestTable values (N'أحمد');
INSERT INTO TestTable values (N'إحمد');
INSERT INTO TestTable values (N'ءحمد');

porque ء, أ, إ son todos para SQL son parte de hamza que es ء

Entonces, si ejecuta la consulta

SELECT * 
FROM TestTable 
WHERE ArabicChars like 'ء%'

te mostrará

أحمد
إحمد

así que para resumir la historia larga

a SQL not no es = a ا porque sus 2 letras diferentes son hamza y alefp

pero ء = آ = أ = ؤ = إ = ئ

todos son Hamza ء

AmmarR
fuente
Great work @AmmarR
George Botros
1

Este es uno de los problemas más complicados por los que he pasado

así que les escribiré todo lo que intenté que no funcionó, tal vez puedan comenzar después de eso

 CREATE TABLE [dbo].[TestTable]  (
    [ArabicChars] [nvarchar](50) COLLATE Arabic_CI_AI NOT NULL,

    CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED 
    (
       [ArabicChars] ASC
    )
) ON [PRIMARY];

creé su columna usando COLLATE Arabic_CI_AI donde CI = no distingue entre mayúsculas y minúsculas y AI = no tiene acento, y aquí es donde se supone que funciona porque si elige otro idioma como por ejemplo S y Š, funciona

También intenté cambiar la intercalación de la base de datos a Arabic_CI_AI todavía no funcionó

también puedes cotejar el script como

SELECCIONAR * DE la tabla de prueba DONDE ArabicChars COLLATE Arabic_CI_AI como 'ا%' COLLATE Arabic_CI_AI;

y aun así no funcionó

mira este artículo habla sobre el mismo problema pero desde el punto de clasificación

http://technet.microsoft.com/en-us/library/cc295829(SQL.90).aspx

esto está tomado del artículo

Por ejemplo, un orden de clasificación define si el carácter árabe '' es menor que, igual o mayor que ''. También define si la intercalación es sensible al acento (por ejemplo, si '' es igual o no es '').

Aquí hay otra persona que investigó este problema pero no pudo encontrar ninguna solución http://www.siao2.com/2008/11/11/9056745.aspx

tratando de ignorar diacríticos o hamza, supongo que actualmente no es posible en el servidor sql

pueden ser versiones futuras

AmmarR
fuente
Good Work @AmmarR
George Botros
0

Para el propósito mencionado en esta publicación, solo puede usar: SQL_Latin1_General_CP1251_CI_AS [funciona para juegos de caracteres en árabe y persa, así como en inglés / latín].

usuario80831
fuente