การรักษาตัวอักษรอาหรับบางตัวเหมือนกัน


10

ในภาษาอาหรับเรามีอักขระเช่นا (alef) และأ (alef with hamza)

ผู้ใช้เขียนพวกเขาแทนกันและเราต้องการค้นหาพวกเขาสลับกันได้ SQL Server ถือว่าเป็นอักขระแยกต่างหาก ฉันจะทำให้ SQL ปฏิบัติต่อพวกเขาในลักษณะเดียวกันได้อย่างไร?

ฉันคิดว่าจะแทนที่أ (alef กับ hamza) ด้วยا (alef) ที่ใส่เข้าไป แต่เรามีทางเลือกมากมายในภาษาอาหรับไม่ใช่แค่แค่ا (alef) และأ (alef กับ hamza)

ฉันพยายามArabic_CI_ASแล้วArabic_CI_AIแต่นั่นก็ไม่ได้แก้ปัญหา

นี่คือสคริปต์ในการสร้างปัญหาใหม่:

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

ผลลัพธ์คือ:

ArabicChars 

احمد

(1 row(s) affected)

ผลลัพธ์ที่ต้องการจะเป็นทั้งสองแถวที่เราแทรกเข้าไป


ไม่มีปัญหา. Aaron Bertrand มีสคริปต์เล็ก ๆ น้อย ๆที่คุณสามารถปรับตัวเพื่อทดสอบการเปรียบเทียบที่เป็นไปได้ทั้งหมด อย่างไรก็ตามฉันสงสัยว่าไม่มีการเปรียบเทียบจะพิจารณาอักขระสองตัวนี้เหมือนกัน
Nick Chammas

แต่คุณมีสองตัวอักษรที่แตกต่างกันในชื่อที่ระบุไว้อย่างน้อยก็ในลักษณะที่ปรากฏ และแน่นอนฉันคิดว่าพวกเขาควรได้รับการปฏิบัติเหมือนตัวอักษรที่แตกต่างกันا and أ
nuux

3
@NickChammas ตามที่คุณเดา SOUNDEX () ส่งคืน 0000 สำหรับอักขระภาษาอาหรับใด ๆ
George Botros

1
@NickChammas: ซึ่งเป็นปัญหาแล้ว: พฤติกรรมของผู้ใช้ + ข้อสมมติที่แตกต่างจากพฤติกรรมการเรียงที่เข้มงวด
GBN

1
@gbn - เนื่องจากว่าตัวอักษรเหล่านี้แตกต่างกันฉันจะบอกว่าปัญหาคือการให้ความรู้แก่ผู้ใช้ หากผู้ใช้ต้องการให้จดหมายเหล่านั้นได้รับการปฏิบัติอย่างเท่าเทียมกันโดยเฉพาะอย่างยิ่งในการค้นหาแล้วฟังก์ชันนั้นจะต้องถูกสร้างขึ้นอย่างชัดเจน มันไม่ใช่ปัญหาการเปรียบเทียบ
Nick Chammas

คำตอบ:


4

ฉันทำแบบทดสอบไม่กี่ครั้งและฉันคิดว่ามันเป็นวิธีการแก้ปัญหา แต่สามารถทำให้งานของคุณเสร็จสิ้นได้เนื่องจาก SQL เพราะตัวมันเองไม่ได้ช่วยอะไรมาก

หากคุณสังเกตเห็นว่ายูนิโค้ดของตัวละครเหล่านี้อยู่ใกล้กัน

select unicode(N'أ')
  = 1571

select unicode(N'ا')
  = 1575

select unicode(N'إ')
  = 1573

ดังนั้นระหว่างأถึง,, มันคือตั้งแต่ 1571 ถึง 1575 หรือถ้าคุณต้องการให้แน่ใจว่าคุณได้ทุกสิ่งระหว่างนั้น

ตรวจสอบให้แน่ใจว่าคุณรวมตั้งแต่ 1569 ถึง 1575

ซึ่งก็คือ

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

ดังนั้นเพื่อให้แน่ใจว่าคุณรวมทุกสิ่งที่คล้ายกันในการค้นหาของคุณคุณสามารถใช้นิพจน์ทั่วไป

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

ดังนั้นในกรณีนี้คุณจะได้อักขระทั้งหมดระหว่างءถึงاซึ่งรวมอักขระทั้งหมดระหว่าง 1569 ถึง 1575

ดังนั้นในกรณีนี้ถ้าตารางของคุณมี

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

แบบสอบถามข้างต้นจะทำให้พวกเขาทั้งหมด

แต่คุณจะสังเกตเห็นบางสิ่งที่ตลก

หากคุณมีคอลัมน์เป็นคีย์หลัก

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

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

คุณจะไม่สามารถแทรก 2 ระเบียนนี้

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

เนื่องจากء, أ, إนั้นเป็นของ SQL ทั้งหมดจึงเป็นส่วนหนึ่งของ hamza ซึ่งก็คือء

ดังนั้นหากคุณเรียกใช้แบบสอบถาม

SELECT * 
FROM TestTable 
WHERE ArabicChars like 'ء%'

มันจะแสดงให้คุณ

أحمد
إحمد

เพื่อให้ได้เนื้อเรื่องที่สั้น

ถึง SQL أไม่ได้ = ถึงاเพราะมันมีตัวอักษรต่างกัน 2 ตัวคือ hamza และ alefp

แต่ء = آ = أ = ؤ = إ = ئ

พวกเขาทั้งหมด Hamza ء


ผลงานยอดเยี่ยม @AmmarR
George Botros

1

นี่เป็นหนึ่งในปัญหาที่ซับซ้อนที่สุดที่ฉันเคยผ่านมา

ดังนั้นฉันจะเขียนทุกสิ่งที่ฉันพยายามที่ไม่ทำงานอาจเป็นคุณสามารถเริ่มต้นหลังจากนั้น

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

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

ฉันสร้างคอลัมน์ของคุณโดยใช้ COLLATE Arabic_CI_AI โดยที่ CI = case insensitive และ AI = สำเนียง insensitive และนี่คือที่ที่มันควรจะทำงานเพราะถ้าคุณเลือกภาษาอื่นเช่น S และŠมันใช้งานได้

ฉันยังพยายามเปลี่ยนการจัดเรียงฐานข้อมูลเป็น Arabic_CI_AI ยังคงไม่ทำงาน

คุณสามารถจัดเรียงสคริปต์เช่น

SELECT * จาก TestTable WHERE ArabicChars COLLATE Arabic_CI_AI เช่น 'ا%' COLLATE Arabic_CI_AI;

และมันก็ยังไม่ทำงาน

ตรวจสอบบทความนี้มันพูดเกี่ยวกับปัญหาเดียวกัน แต่จากจุดเรียงลำดับ

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

สิ่งนี้นำมาจากบทความ

ตัวอย่างเช่นการเรียงลำดับจะกำหนดว่าอักขระภาษาอาหรับ '' น้อยกว่า, เท่ากับหรือมากกว่า '' นอกจากนี้ยังกำหนดว่าการเปรียบเทียบนั้นมีความอ่อนไหวต่อสำเนียงหรือไม่ (เช่นไม่ว่า '' จะเท่ากันหรือไม่เท่ากับ '')

ที่นี่เป็นอีกคนที่ค้นคว้าปัญหานี้ แต่ไม่สามารถหาวิธีแก้ปัญหาใด ๆ ได้ http://www.siao2.com/2008/11/11/9056745.aspx

พยายามละเว้นกำกับหรือ hamza ฉันเดาไม่ได้ในเซิร์ฟเวอร์ sql ในขณะนี้

อาจเป็นรุ่นในอนาคต


Good Work @AmmarR
George Botros

0

สำหรับวัตถุประสงค์ที่กล่าวถึงในโพสต์นี้คุณสามารถใช้: SQL_Latin1_General_CP1251_CI_AS [มันใช้งานได้สำหรับชุดภาษาอารบิกและเปอร์เซียและภาษาอังกฤษ / ละติน]

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.