ละเว้นการเน้นเสียงใน 'ที่ไหน'


17

ในฐานข้อมูลของเราเรามีหลายรายการที่มี caron / hatschek ตอนนี้ผู้ใช้ของเราต้องการค้นหารายการรวมถึง caron / hatschek เมื่อค้นหารายการที่ไม่มี ฉันจะแสดงสิ่งนี้ด้วยตัวอย่างง่ายๆ:

ในฐานข้อมูลของเราเรามีรายการ (ติดต่อกับชื่อ)

Millière

ดังนั้นชื่อนี้ถูกต้องในประเทศที่บุคคลนั้นอาศัยอยู่

ในประเทศของเราเราไม่ได้มีตัวอักษรใด ๆ กับรอน / hatschek Milliereดังนั้นผู้ใช้ค้นหาของเราสำหรับ ไม่มีผลการค้นหาขึ้นมาเป็นไม่ชัดไม่ตรงกับèe

ผมไม่มีความคิดวิธีนี้อาจจะตระหนักว่าé, è, êและอื่น ๆ อีกมากมายที่มีอยู่ (และนี่เป็นเพียงตัวอย่างจดหมายe... )

(วิธีอื่นจะง่ายกว่ามากเพราะฉันสามารถแทนที่ตัวอักษรทั้งหมดด้วย caron / hatschek ด้วยตัวอักษรพื้นฐานได้อย่างชัดเจนเห็นได้ชัดว่าผู้ใช้ของเราต้องการชื่อรุ่นที่ถูกต้องในฐานข้อมูลไม่ใช่คนพิการ)


โปรดทราบว่าตัวอักษร "è" ไม่มี caron / hacek แต่มีสำเนียงที่ร้ายแรง รอน / hacek จะเป็น "ě" คุณหมายถึง "ตัวละครที่เน้นเสียง" หรืออะไรแบบนั้น? หรือคุณหมายถึงสำเนียง caron / hacek โดยเฉพาะ?
psmears

ผมหมายถึงตัวอักษรใด ๆ กับ "สัญญาณ" (ขออภัยผมไม่ทราบชื่อจริงมัน.
Lumo

คำตอบ:


31

ปัญหานี้สามารถแก้ไขได้โดยใช้การเปรียบเทียบที่ไม่ถูกต้อง

ฐานข้อมูลของคุณอาจใช้การเปรียบเทียบ AS (การเน้นข้อความที่มีความสำคัญ) ดังนั้นโดยค่าเริ่มต้นมันจะค้นหาการจับคู่ที่ตรงกันรวมถึงการเน้น

คุณสามารถแนะนำส่วนคำสั่ง WHERE ที่จะใช้การเปรียบเทียบใหม่กว่าฐานข้อมูลเริ่มต้นโดยการระบุการเปรียบเทียบกับการเปรียบเทียบ

ในdbfiddle นี้ฉันสร้างตัวอย่างโดยใช้การเปรียบเทียบ LATIN1 แต่คุณสามารถใช้วิธีการเดียวกันกับการเปรียบเทียบที่คุณกำลังใช้เพียงแค่เปลี่ยน AS เป็น AI สำหรับการเรียงคอลัมน์ที่คอลัมน์ของคุณกำลังใช้อยู่

ใช้การจัดเรียง Accent Insensitive ที่ตรงกับการเรียงที่ colummn ใช้ ตัวอย่างเช่นหากคอลัมน์กำลังใช้SQL_Latin1_General_CP1_CI_ASใช้SQL_Latin1_General_CP1_CI_AIและไม่Latin1_General_CI_ASหรือLatin1_General_100_CI_ASรูปแบบใด ๆ ของทั้งสองนั้นเนื่องจากพฤติกรรมของการเปรียบเทียบที่ไม่ใช่ SQL_ จะแตกต่างกันไปในหลาย ๆ ทางมากกว่าการใช้สำเนียงที่เน้นความรู้สึกและอาจไม่คาดหวังจากผู้ใช้

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

อ่านผ่านการใช้ SQL Server Collationsสำหรับข้อมูลเพิ่มเติม

จากนั้นอีกครั้งคุณอาจต้องการเรียงลำดับเพื่อใช้การเปรียบเทียบนี้ (ตามที่peufeuระบุไว้ในความคิดเห็น) เพื่อให้แน่ใจว่า "é" เรียงลำดับด้วย "e" มิฉะนั้นคนที่เลขหน้าในผลลัพธ์ตามลำดับตัวอักษรจะแปลกใจที่จะไม่พบ "é" ที่พวกเขาคาดหวังว่าพวกเขาจะเป็น แต่ถ้าคุณเพียงแค่ต้องการสัมผัสแบบสอบถามนี้คุณสามารถเพิ่มส่วนCOLLATEคำสั่งได้ORDER BYเช่นกัน

ตามที่ระบุไว้โดยSolomon Rutzkyในความคิดเห็นหากสิ่งนี้มีผลกับ 1 หรือคอลัมน์ไม่กี่ตัวเลือกอื่นคือการสร้างคอลัมน์ที่ไม่ได้คำนวณที่ยังคงอยู่ซึ่งเพียงแค่ทำซ้ำคอลัมน์ "ชื่อ" และให้การเรียงแบบเน้นเสียงแบบอ่อน คอลัมน์. หลีกเลี่ยงการสแกนที่เกิดจากการเปลี่ยนการเรียงภายในแบบสอบถาม ดังนั้นแบบสอบถามจำเป็นต้องกรองในคอลัมน์ใหม่

สิ่งที่ต้องการ:

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

หรือคุณสามารถสร้างมุมมองแทนการเพิ่มคอลัมน์ที่คำนวณได้ (ตามที่jyaoต้องการ)


1
Tom: ฉันจะสังเกตเห็น (และเน้น) ว่าพวกเขาควรใช้ Accation-Insensitive รุ่นของ Collation ที่คอลัมน์กำลังใช้ (การเปรียบเทียบเริ่มต้นของฐานข้อมูลที่กล่าวถึงในวรรค 3 ไม่เกี่ยวข้องกับคำถามนี้) หากมีการใช้คอลัมน์SQL_Latin1_General_CP1_CI_ASให้ใช้SQL_Latin1_General_CP1_CI_AIและไม่Latin1_General_CI_ASหรือLatin1_General_100_CI_ASรูปแบบใด ๆ ของทั้งสองนั้นเนื่องจากพฤติกรรมของการไม่SQL_เรียงตัวจะแตกต่างกันมากกว่าการใช้สำเนียงที่เน้นความรู้สึกและอาจไม่คาดหวังจากผู้ใช้ sys.columnsการเปรียบเทียบจะพบได้ใน
โซโลมอน Rutzky

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