Traktowanie niektórych znaków arabskich jako identycznych


10

W języku arabskim mamy znaki takie jak ا (alef) i أ (alef with hamza).

Użytkownicy piszą je zamiennie, a my chcemy je wyszukiwać zamiennie. SQL Server traktuje je jako osobne znaki. Jak zmusić SQL do traktowania ich jako tego samego znaku?

Pomyślałem, że przy wstawianiu mogę zastąpić dowolne أ (alef z hamza) przez ا (alef), ale mamy wiele alternatyw w języku arabskim, nie tylko ا (alef) i أ (alef z hamza).

Próbowałem Arabic_CI_ASi Arabic_CI_AIale to nie rozwiązuje problemu.

Oto skrypt do ponownego wygenerowania problemu:

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

Wynik to:

ArabicChars 

احمد

(1 row(s) affected)

Pożądanym rezultatem byłyby oba wstawione wiersze.


Nie ma problemu. Aaron Bertrand ma ładny mały skrypt , który można dostosować, aby przetestować wszystkie możliwe układy. Podejrzewam jednak, że żadne zestawienie nie uzna tych dwóch znaków za takie same.
Nick Chammas

ale masz dwa różne znaki w podanych nazwach, przynajmniej z wyglądu. I oczywiście uważam, że należy je traktować jako różne znakiا and أ
nuux

3
@NickChammas, jak zgadłeś SOUNDEX () zwraca 0000 dla dowolnego arabskiego znaku
George Botros

1
@NickChammas: na czym polega problem: zachowanie użytkownika + założenie różni się od bardziej rygorystycznego zachowania sortowania.
gbn

1
@ gbn - Biorąc pod uwagę, że są to różne litery, powiedziałbym, że problemem jest edukacja użytkowników. Jeśli użytkownicy chcą, aby te litery były traktowane jednakowo - zwłaszcza podczas wyszukiwania - ta funkcja musi zostać wyraźnie zbudowana. To nie jest kwestia sortowania.
Nick Chammas,

Odpowiedzi:


4

Zrobiłem kilka testów i myślę, że to jest obejście, ale może zrobić swoją pracę, ponieważ SQL sam w sobie nie pomaga.

jeśli zauważysz, że Unicode tych znaków są blisko siebie

select unicode(N'أ')
  = 1571

select unicode(N'ا')
  = 1575

select unicode(N'إ')
  = 1573

więc między أ i ا, to od 1571 do 1575 lub jeśli chcesz mieć pewność, że dostaniesz wszystko pomiędzy

upewnij się, że podałeś od 1569 do 1575

które są

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

Aby upewnić się, że w wyszukiwaniu uwzględnisz wszystkie podobne elementy, możesz użyć wyrażeń regularnych

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

więc w tym przypadku otrzymujesz wszystkie znaki od ء do ا, które obejmują wszystkie między 1569 a 1575

więc w tym przypadku, jeśli Twój stół ma

 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'إحمد');

powyższe zapytanie otrzyma je wszystkie.

ale zauważysz coś śmiesznego

jeśli masz kolumnę jako klucz podstawowy

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

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

nie będzie można wstawić tych 2 rekordów

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

ponieważ wszystkie ء, أ, إ są SQL, są częścią hamza, która jest ء

Więc jeśli uruchomisz zapytanie

SELECT * 
FROM TestTable 
WHERE ArabicChars like 'ء%'

pokaże ci

أحمد
إحمد

więc krótko mówiąc

na SQL أ nie jest = na ا, ponieważ ma 2 różne litery hamza i alefp

ale ء = آ = أ = ؤ = إ = ئ

wszyscy oni są Hamza ء


Świetna robota @AmmarR
George Botros

1

jest to jeden z najbardziej skomplikowanych problemów, przez które przeszedłem

więc napiszę wam wszystko, co próbowałem, ale nie zadziałało, być może możecie zacząć od tego

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

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

utworzyłem twoją kolumnę przy użyciu COLLATE Arabic_CI_AI, gdzie CI = bez rozróżniania wielkości liter i AI = bez uwzględniania akcentu, i tam powinien działać, ponieważ jeśli wybierzesz inny język, na przykład S i Š, to działa

Próbowałem także zmienić sortowanie bazy danych na Arabic_CI_AI nadal nie działało

możesz także zestawić skrypt jak

WYBIERZ * Z TABELI Testowej GDZIE ArabicChars COLLATE Arabic_CI_AI jak 'ا%' COLLATE Arabic_CI_AI;

i nadal nie działało

sprawdź ten artykuł mówi o tym samym problemie, ale od punktu sortowania

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

pochodzi z tego artykułu

Na przykład kolejność sortowania określa, czy arabski znak „” jest mniejszy, równy lub większy niż „”. Określa również, czy sortowanie jest wrażliwe na akcent (na przykład, czy „” jest równe, czy nie jest równe „”).

oto inna osoba, która badała ten problem, ale nie mogła znaleźć żadnego rozwiązania http://www.siao2.com/2008/11/11/9056745.aspx

próbuje zignorować znaki diakrytyczne lub hamza i chyba nie jest możliwe na serwerze SQL

mogą być przyszłe wersje


Dobra robota @AmmarR
George Botros

0

Do celów wymienionych w tym poście możesz używać tylko: SQL_Latin1_General_CP1251_CI_AS [działa w przypadku zestawów znaków arabskich i perskich oraz angielskich / łacińskich].

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.