การจัดทำดัชนีกับสตริงที่ไม่คำนึงถึงขนาดตัวพิมพ์ แต่เคสของข้อมูลยังคงอยู่ มันใช้งานได้จริงอย่างไร?
นี่ไม่ใช่พฤติกรรมที่เฉพาะเจาะจงของ SQL Server แต่เป็นสิ่งที่สิ่งเหล่านี้ทำงานโดยทั่วไป
ดังนั้นข้อมูลคือข้อมูล หากคุณกำลังพูดเกี่ยวกับดัชนีเฉพาะข้อมูลที่ต้องการจะถูกเก็บไว้เป็นมันเป็นอื่นมันจะต้องมีการมองขึ้นในตารางหลักในแต่ละครั้งจะได้รับค่าที่เกิดขึ้นจริงและจะมีความเป็นไปได้ของดัชนีที่ครอบคลุมไม่มี (อย่าง อย่างน้อยไม่ได้สำหรับประเภทสตริง)
ข้อมูลทั้งในตาราง / ดัชนีคลัสเตอร์หรือดัชนีที่ไม่ใช่คลัสเตอร์ไม่ได้มีการตรวจทาน / ข้อมูลใด ๆ เรียงลำดับ มันเป็นเพียงข้อมูล การจัดเรียง (โลแคล / กฎของวัฒนธรรมและความไว) เป็นเพียงข้อมูลเมตาที่แนบมากับคอลัมน์และใช้เมื่อเรียกใช้การดำเนินการเรียงลำดับ (เว้นแต่จะถูกแทนที่โดยCOLLATE
ข้อ) ซึ่งจะรวมถึงการสร้าง / สร้างใหม่ของดัชนี กฎที่กำหนดโดยการเปรียบเทียบที่ไม่ใช่ไบนารีถูกใช้เพื่อสร้างการเรียงลำดับคีย์ซึ่งเป็นการแทนไบนารีของสตริง (คีย์การเรียงลำดับไม่จำเป็นในการเปรียบเทียบไบนารี) การเป็นตัวแทนไบนารีเหล่านี้รวมกฎของโลแคล / วัฒนธรรมและความไวที่เลือกไว้ทั้งหมด การเรียงลำดับคีย์ถูกใช้เพื่อวางเร็กคอร์ดในลำดับที่เหมาะสม แต่จะไม่ถูกเก็บไว้ในดัชนีหรือตาราง พวกเขาจะไม่ถูกเก็บไว้ (อย่างน้อยฉันไม่ได้เห็นค่าเหล่านี้ในดัชนีและบอกว่าพวกเขาไม่ได้เก็บไว้) เพราะ:
- พวกเขาไม่จำเป็นต้องเรียงลำดับอย่างแท้จริงเพราะพวกเขาจะอยู่ในลำดับเดียวกับแถวในตารางหรือดัชนีอย่างไรก็ตาม แต่ลำดับทางกายภาพของดัชนีเป็นเพียงการเรียงลำดับไม่ใช่การเปรียบเทียบ
- ในขณะที่การจัดเก็บอาจทำให้การเปรียบเทียบเร็วขึ้น แต่ก็จะทำให้ดัชนีมีขนาดใหญ่ขึ้นเนื่องจากขนาดต่ำสุดสำหรับอักขระตัวเดียวคือ 5 ไบต์และนั่นเป็นเพียง "ค่าใช้จ่าย" (ของโครงสร้างคีย์การเรียงลำดับ) อักขระส่วนใหญ่มีขนาด 2 ไบต์และอีก 1 ไบต์หากมีการเน้นเสียงและอีก 1 ไบต์หากเป็นตัวพิมพ์ใหญ่ ตัวอย่างเช่น "e" เป็นคีย์ขนาด 7 ไบต์ "E" และ "é" มีทั้ง 8 ไบต์และ "É" เป็นคีย์ขนาด 9 ไบต์ ดังนั้นอย่าเก็บสิ่งเหล่านี้ไว้ในที่สุด
การเปรียบเทียบมีสองประเภท: SQL Server และ Windows
เซิร์ฟเวอร์ SQL
การเปรียบเทียบ SQL Server (ชื่อที่ขึ้นต้นด้วยSQL_
) เป็นวิธีการเรียงลำดับ / เปรียบเทียบก่อนหน้าของ SQL Server 2000 (แม้ว่าSQL_Latin1_General_CP1_CI_AS
จะยังคงเป็นค่าเริ่มต้นในการติดตั้งบนระบบปฏิบัติการภาษาอังกฤษของสหรัฐฯ ในรูปแบบเก่าที่เรียบง่ายไม่ใช่ยูนิโคดการรวมกันของสถานที่เกิดเหตุหน้ารหัสและความไวต่างๆจะได้รับการทำแผนที่แบบคงที่ของตัวละครแต่ละตัวในหน้ารหัสที่ อักขระแต่ละตัวได้รับการกำหนดค่า (เช่นน้ำหนักการเรียงลำดับ) เพื่อแสดงว่ามันมีความสอดคล้องกับอักขระอื่นอย่างไร การเปรียบเทียบในรุ่นนี้ดูเหมือนจะเป็นการดำเนินการสองรอบ:
- ก่อนอื่นมันจะกำจัดสำเนียงทั้งหมด (เช่น " ü " กลายเป็น " u ") ขยายตัวอักขระเช่น " Æ " เป็น " A " และ " E " จากนั้นทำการเรียงลำดับเริ่มต้นเพื่อให้คำเรียงตามลำดับตามธรรมชาติ คาดว่าจะพบพวกเขาในพจนานุกรม)
- จากนั้นมันจะไปตามตัวอักษรเพื่อกำหนดความเท่าเทียมกันตามค่าพื้นฐานเหล่านี้ต่อตัวละครแต่ละตัว นี้ส่วนที่สองคือสิ่งที่ mustaccio จะอธิบายในคำตอบของเขา
ความไวต่อแสงเพียงอย่างเดียวที่สามารถปรับได้ในการเปรียบเทียบนี้คือ: "ตัวพิมพ์ใหญ่" และ "เน้น" ("ความกว้าง", "ประเภทคะนะ" และ "ตัวเลือกชุดรูปแบบ" ไม่พร้อมใช้งาน) นอกจากนี้ยังไม่มีการเปรียบเทียบเหล่านี้ที่สนับสนุนอักขระเพิ่มเติม (ซึ่งสมเหตุสมผลว่าเป็น Unicode เฉพาะและการเปรียบเทียบเหล่านี้ใช้กับข้อมูลที่ไม่ใช่ Unicode เท่านั้น)
วิธีการนี้ใช้เพียงเพื่อที่ไม่ใช่ Unicode VARCHAR
ข้อมูล การผสมผสานที่ไม่ซ้ำกันของสถานที่, รหัสหน้า, ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ - เสียงเน้นเสียงมี "รหัสการเรียงลำดับ" เฉพาะซึ่งคุณสามารถดูได้ในตัวอย่างต่อไปนี้:
SELECT COLLATIONPROPERTY(N'SQL_Latin1_General_CP1_CI_AS', 'SortID'), -- 52
COLLATIONPROPERTY(N'SQL_Latin1_General_CP1_CS_AS', 'SortID'), -- 51
COLLATIONPROPERTY(N'Latin1_General_100_CI_AS', 'SortID'); -- 0
ข้อแตกต่างระหว่างการเปรียบเทียบสองครั้งแรกคือการพิจารณาตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ การเปรียบเทียบที่สามคือการเปรียบเทียบ Windows และดังนั้นจึงไม่มีตารางการแมปแบบคงที่
นอกจากนี้การเปรียบเทียบเหล่านี้ควรเรียงลำดับและเปรียบเทียบเร็วกว่าการเปรียบเทียบ Windows เนื่องจากการค้นหาแบบง่ายสำหรับอักขระเพื่อเรียงลำดับน้ำหนัก อย่างไรก็ตามการเปรียบเทียบเหล่านี้ยังใช้งานได้น้อยกว่ามากและควรหลีกเลี่ยงโดยทั่วไปหากเป็นไปได้
ของ windows
การจัดเรียง Windows (ชื่อที่ไม่ได้ขึ้นต้นด้วยSQL_
) เป็นวิธีการเรียงลำดับ / การเปรียบเทียบที่ใหม่กว่า (เริ่มต้นใน SQL Server 2000) ในโมเดล Unicode ที่ใหม่กว่าซับซ้อนนี้การรวมกันของสถานที่เกิดเหตุแต่ละหน้ารหัสและความไวที่แตกต่างกันจะไม่ได้รับการทำแผนที่แบบคงที่ สิ่งหนึ่งที่ไม่มีรหัสหน้าในรุ่นนี้ รุ่นนี้กำหนดค่าการเรียงเริ่มต้นให้กับแต่ละอักขระจากนั้นแต่ละโลแคล / วัฒนธรรมสามารถกำหนดค่าการเรียงใหม่ให้กับจำนวนอักขระได้ สิ่งนี้ทำให้หลายวัฒนธรรมสามารถใช้อักขระเดียวกันในวิธีที่ต่างกัน สิ่งนี้มีผลต่อการอนุญาตให้เรียงหลายภาษาโดยธรรมชาติโดยใช้การเรียงเดียวกันหากไม่ใช้อักขระเดียวกัน (และหากหนึ่งในนั้นไม่จำเป็นต้องกำหนดค่าใหม่อีกครั้งและสามารถใช้ค่าเริ่มต้นได้)
ค่าการเรียงลำดับในรุ่นนี้ไม่ใช่ค่าเดียว พวกมันคืออาร์เรย์ของค่าที่กำหนดน้ำหนักสัมพัทธ์ให้กับตัวอักษรฐานการกำกับเสียงใด ๆ (เช่นการเน้นเสียง) การบรรจุและอื่น ๆ หากการเปรียบเทียบเป็นแบบตัวพิมพ์ใหญ่และตัวเล็กต้องใช้ส่วน "case" ของอาร์เรย์นั้น ด้วยเหตุนี้จึงไม่มีความรู้สึก) หากการเปรียบเทียบนั้นมีความอ่อนไหวต่อสำเนียงดังนั้นส่วน "diacritic" ของอาร์เรย์จะถูกนำมาใช้มิฉะนั้นก็จะถูกละเว้น
การเปรียบเทียบในรุ่นนี้เป็นการทำงานแบบมัลติพาส:
- ก่อนอื่นสตริงจะถูกทำให้เป็นมาตรฐานเพื่อให้วิธีที่หลากหลายในการแสดงอักขระเดียวกันจะถือเอา ตัวอย่างเช่น " ü " อาจเป็นอักขระ / จุดรหัสเดียว (U + 00FC) คุณสามารถรวม " u " ที่ไม่เน้นเสียงได้(U + 0075) เข้ากับการรวมการรวม " ̈ " (U + 0308) เพื่อรับ: " ü " ซึ่งไม่เพียง แต่ดูเหมือนจะเหมือนกันเมื่อเรนเดอร์ (เว้นแต่มีปัญหากับ แบบอักษรของคุณ) แต่ก็ถือว่าเหมือนกันกับเวอร์ชันอักขระตัวเดียว (U + 00FC) ยกเว้นว่าใช้การเปรียบเทียบแบบไบนารี (ซึ่งเปรียบเทียบไบต์แทนอักขระ) การนอร์มัลไลซ์เซชั่นแบ่งอักขระเดี่ยวออกเป็นส่วนต่าง ๆ ซึ่งรวมถึงการขยายสำหรับอักขระเช่น " Æ " (ดังที่ระบุไว้ข้างต้นสำหรับการเปรียบเทียบของ SQL Server)
- การดำเนินการเปรียบเทียบในรุ่นนี้จะมีตัวอักษรต่ออักขระตามความไวแต่ละตัว คีย์การเรียงลำดับสำหรับสตริงจะถูกกำหนดโดยการใช้องค์ประกอบที่เหมาะสมของแต่ละอาร์เรย์เรียงตัวอักษรของค่าตามความไวที่ "ไว" ค่าคีย์การเรียงลำดับจะถูกจัดเรียงโดยความไวหลักทั้งหมดของอักขระแต่ละตัว (อักขระพื้นฐาน) ตามด้วยความไวแสงรองทั้งหมด (น้ำหนักกำกับน้ำหนัก) ตามด้วยน้ำหนักตัวพิมพ์ของแต่ละอักขระและอื่น ๆ
- การเรียงลำดับจะดำเนินการตามคีย์การเรียงลำดับที่คำนวณได้ ด้วยความไวแต่ละอย่างที่จัดกลุ่มไว้ด้วยกันคุณจะได้รับการเรียงลำดับที่แตกต่างจากการเปรียบเทียบ SQL Server ที่เทียบเท่ากันเมื่อเปรียบเทียบสตริงของอักขระหลายตัวและมีการเน้นเสียงที่เกี่ยวข้องและการเปรียบเทียบนั้นมีความอ่อนไหวต่อสำเนียง ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่)
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการเรียงลำดับนี้ในที่สุดฉันจะเผยแพร่โพสต์ที่แสดงค่าคีย์การเรียงลำดับวิธีการคำนวณความแตกต่างระหว่างการเรียง SQL Server และ Windows เป็นต้น แต่สำหรับตอนนี้โปรดดูคำตอบของฉัน: Accent Sensitive Sort ( โปรดทราบว่าคำตอบอื่น ๆ สำหรับคำถามนั้นเป็นคำอธิบายที่ดีของอัลกอริทึม Unicode อย่างเป็นทางการ แต่ SQL Server ใช้การกำหนดเองแทนแม้ว่าจะคล้ายกันอัลกอริทึมและแม้แต่ตารางน้ำหนักแบบกำหนดเอง)
ความไวแสงทั้งหมดสามารถปรับได้ในการจัดเรียงเหล่านี้: "case", "accent", "width", "kana type" และ "select selector" (เริ่มใน SQL Server 2017 และสำหรับ Collation ญี่ปุ่นเท่านั้น) นอกจากนี้การเปรียบเทียบเหล่านี้บางส่วน (เมื่อใช้กับข้อมูล Unicode) สนับสนุนอักขระเพิ่มเติม (เริ่มต้นใน SQL Server 2012) วิธีการนี้ใช้กับทั้งสองNVARCHAR
และ VARCHAR
ข้อมูล (แม้แต่ข้อมูลที่ไม่ใช่ Unicode) มันใช้กับข้อมูลที่ไม่ใช่ Unicode VARCHAR
โดยการแปลงค่าเป็น Unicode ภายในก่อนจากนั้นจึงใช้กฎการเรียงลำดับ / การเปรียบเทียบ
โปรดทราบ:
- ไม่มีการเปรียบเทียบค่าเริ่มต้นสากลสำหรับ SQL Server มีค่าเริ่มต้นการติดตั้งซึ่งแตกต่างกันไปตามการตั้งค่าภาษา / ภาษาปัจจุบันของระบบปฏิบัติการ ณ เวลาที่ทำการติดตั้ง (ซึ่งน่าเสียดาย
SQL_Latin1_General_CP1_CI_AS
สำหรับระบบภาษาอังกฤษของสหรัฐอเมริกาดังนั้นโปรดลงคะแนนสำหรับคำแนะนำนี้ ) สิ่งนี้สามารถเปลี่ยนแปลงได้ระหว่างการติดตั้ง การเปรียบเทียบระดับอินสแตนซ์นี้จากนั้นตั้งค่าการเรียงสำหรับ[model]
ฐานข้อมูลซึ่งเป็นเทมเพลตที่ใช้เมื่อสร้างฐานข้อมูลใหม่ แต่การเปรียบเทียบสามารถเปลี่ยนแปลงได้เมื่อดำเนินการCREATE DATABASE
โดยการระบุCOLLATE
ข้อ การเปรียบเทียบระดับฐานข้อมูลนี้ใช้สำหรับตัวแปรและตัวอักษรสตริงเช่นเดียวกับค่าเริ่มต้นสำหรับคอลัมน์ใหม่ (และเปลี่ยนแปลง!) เมื่อCOLLATE
ไม่ได้ระบุอนุประโยค (ซึ่งเป็นกรณีสำหรับรหัสตัวอย่างในคำถาม)
- สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Collations / encodings / Unicode โปรดไปที่: Collations Info