Traiter certains caractères arabes comme identiques


10

En arabe, nous avons des caractères comme ا (alef) et أ (alef avec hamza).

Les utilisateurs les écrivent de manière interchangeable et nous voulons les rechercher de manière interchangeable. SQL Server les traite comme des caractères distincts. Comment puis-je faire en sorte que SQL les traite comme le même caractère?

J'ai pensé remplacer n'importe quel أ (alef avec hamza) par ا (alef) à l'insertion mais nous avons beaucoup d'alternatives en langue arabe non seulement ا (alef) et أ (alef avec hamza).

J'ai essayé Arabic_CI_ASet Arabic_CI_AIcela ne résout pas le problème.

Voici un script pour régénérer le problème:

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'ا%';

Le résultat est:

ArabicChars 

احمد

(1 row(s) affected)

Le résultat souhaité serait les deux lignes que nous avons insérées.


Aucun problème. Aaron Bertrand a un joli petit script que vous pouvez adapter pour tester toutes les collations possibles. Cependant, je suppose qu'aucune collation ne considérera ces deux personnages comme les mêmes.
— Nick Chammas

mais vous avez deux caractères différents dans les noms indiqués, au moins en apparence. Et bien sûr, je pense qu'ils devraient être traités comme des caractères différentsا and أ
— nuux

3
@NickChammas comme vous l'avez deviné SOUNDEX () retourne 0000 pour tout caractère arabe
— George Botros

1
@NickChammas: quel est le problème alors: le comportement + l'hypothèse de l'utilisateur diffère du comportement de classement plus strict.
— gbn

1
@gbn - Étant donné qu'il s'agit de lettres différentes, je dirais que le problème est l'éducation des utilisateurs. Si les utilisateurs veulent que ces lettres soient traitées de manière égale - en particulier dans une recherche - alors cette fonctionnalité doit être explicitement construite. Ce n'est pas un problème de classement.
— Nick Chammas

Réponses:


4

J'ai fait quelques tests et je suppose que c'est un travail à faire, mais je peux faire votre travail, car SQL lui-même n'aide pas beaucoup.

si vous remarquez que les unicodes de ces caractères sont proches les uns des autres

select unicode(N'أ')
  = 1571

select unicode(N'ا')
  = 1575

select unicode(N'إ')
  = 1573

donc entre أ et ا, c'est de 1571 à 1575 ou si vous voulez vous assurer d'avoir tout entre les deux

assurez-vous d'inclure de 1569 à 1575

qui sont

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

Donc, pour vous assurer d'inclure tout ce qui est similaire dans votre recherche, vous pouvez utiliser des expressions régulières

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

dans ce cas, vous obtenez tous les caractères entre ء et ا qui incluent tous ceux entre 1569 et 1575

dans ce cas, si votre table a

 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 requête ci-dessus les obtiendra tous.

mais vous remarquerez quelque chose de drôle

si vous avez votre colonne comme clé primaire

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

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

vous ne pourrez pas insérer ces 2 enregistrements

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

parce que les ء, أ, إ sont tous en SQL font partie de hamza qui est ء

Donc, si vous exécutez la requête

SELECT * 
FROM TestTable 
WHERE ArabicChars like 'ء%'

ça vous montrera

أحمد
إحمد

donc pour faire court

à SQL أ n'est pas = à ا car ses 2 lettres différentes hamza et alefp

mais ء = آ = أ = ؤ = إ = ئ

ils sont tous Hamza ء


Excellent travail @AmmarR
— George Botros

1

c'est l'un des problèmes les plus compliqués que j'ai traversés

donc je vais vous écrire tout ce que j'ai essayé qui n'a pas fonctionné, peut-être que vous pouvez commencer après cela

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

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

j'ai créé votre colonne en utilisant COLLATE Arabic_CI_AI où CI = insensible à la casse et AI = insensible à l'accent, et c'est là que son suppose de fonctionner parce que si vous avez choisi une autre langue comme par exemple S et Š, cela fonctionne

j'ai également essayé de changer le classement de la base de données en Arabic_CI_AI ne fonctionnait toujours pas

vous pouvez également assembler le script comme

SELECT * FROM TestTable WHERE ArabicChars COLLATE Arabic_CI_AI comme 'ا%' COLLATE Arabic_CI_AI;

et ça n'a toujours pas marché

consultez cet article, il parle du même problème, mais du point de tri

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

cela est tiré de l'article

Par exemple, un ordre de tri définit si le caractère arabe «» est inférieur, égal ou supérieur à «». Il définit également si le classement est sensible à l'accent (par exemple, si «» est égal ou n'est pas égal à «»).

voici une autre personne qui a recherché ce problème mais n'a trouvé aucune solution http://www.siao2.com/2008/11/11/9056745.aspx

essayer d'ignorer les signes diacritiques ou hamza je suppose que ce n'est pas possible dans le serveur sql actuellement

peut être des versions futures


Good Work @AmmarR
— George Botros

0

Aux fins mentionnées dans cet article, vous ne pouvez utiliser que: SQL_Latin1_General_CP1251_CI_AS [cela fonctionne pour l'arabe et le persan ainsi que pour les jeux de caractères anglais / latin].

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.