SQL Server 2008 และใหม่กว่า
เพียงกรองดัชนีที่ไม่ซ้ำกัน:
CREATE UNIQUE NONCLUSTERED INDEX UQ_Party_SamAccountName
ON dbo.Party(SamAccountName)
WHERE SamAccountName IS NOT NULL;
ในรุ่นที่ต่ำกว่ามุมมองที่เป็นรูปธรรมยังไม่จำเป็น
สำหรับ SQL Server 2005 และรุ่นก่อนหน้าคุณสามารถทำได้โดยไม่มีมุมมอง ฉันเพิ่งเพิ่มข้อ จำกัด ที่ไม่เหมือนใครเช่นที่คุณขอไปยังหนึ่งในตารางของฉัน เนื่องจากฉันต้องการเอกลักษณ์ในคอลัมน์SamAccountName
แต่ฉันต้องการอนุญาตให้ NULL หลายตัวฉันใช้คอลัมน์ materialized แทนมุมมอง materialized:
ALTER TABLE dbo.Party ADD SamAccountNameUnique
AS (Coalesce(SamAccountName, Convert(varchar(11), PartyID)))
ALTER TABLE dbo.Party ADD CONSTRAINT UQ_Party_SamAccountName
UNIQUE (SamAccountNameUnique)
คุณเพียงแค่ใส่บางอย่างในคอลัมน์ที่คำนวณแล้วซึ่งจะรับประกันว่าไม่ซ้ำกันทั่วทั้งตารางเมื่อคอลัมน์ที่ไม่ซ้ำกันที่ต้องการจริงเป็น NULL ในกรณีนี้PartyID
คือคอลัมน์ข้อมูลประจำตัวและการเป็นตัวเลขจะไม่ตรงกันเลยSamAccountName
ดังนั้นจึงใช้งานได้สำหรับฉัน คุณสามารถลองใช้วิธีการของคุณเอง - ให้แน่ใจว่าคุณเข้าใจโดเมนของข้อมูลของคุณเพื่อไม่ให้มีการแยกกับข้อมูลจริง ซึ่งอาจเป็นเรื่องง่ายเหมือนกับการใส่อักขระที่แตกต่างเช่นนี้:
Coalesce('n' + SamAccountName, 'p' + Convert(varchar(11), PartyID))
แม้ว่าจะPartyID
กลายเป็นไม่ใช่ตัวเลขสักวันหนึ่งและสามารถตรงกับ a SamAccountName
, ตอนนี้มันจะไม่สำคัญ
โปรดทราบว่าการมีดัชนีรวมถึงคอลัมน์ที่คำนวณทำให้เกิดผลลัพธ์นิพจน์แต่ละรายการที่จะบันทึกลงดิสก์พร้อมข้อมูลอื่น ๆ ในตารางซึ่งใช้พื้นที่ดิสก์เพิ่มเติม
โปรดทราบว่าหากคุณไม่ต้องการดัชนีคุณยังสามารถบันทึก CPU ได้โดยทำให้นิพจน์ถูกคำนวณล่วงหน้าไปยังดิสก์โดยเพิ่มคำหลักPERSISTED
ลงในส่วนท้ายของนิยามนิพจน์คอลัมน์
ใน SQL Server 2008 ขึ้นไปให้ใช้วิธีการกรองที่แน่นอนแทนหากคุณสามารถทำได้!
การทะเลาะวิวาท
โปรดทราบว่าผู้เชี่ยวชาญด้านฐานข้อมูลบางคนจะเห็นสิ่งนี้เป็น "ตัวแทนตัวแทน" ซึ่งมีปัญหาอย่างแน่นอน (ส่วนใหญ่เกิดจากปัญหาเกี่ยวกับการพยายามพิจารณาว่าบางสิ่งเป็นมูลค่าที่แท้จริงหรือมูลค่าตัวแทนสำหรับข้อมูลที่ขาดหายไปซึ่งอาจเป็นปัญหาได้ ด้วยจำนวนตัวแทนตัวแทนที่ไม่ใช่ค่า NULL คูณอย่างบ้าคลั่ง)
อย่างไรก็ตามฉันเชื่อว่ากรณีนี้แตกต่างกัน คอลัมน์ที่คำนวณที่ฉันเพิ่มจะไม่ถูกใช้เพื่อกำหนดอะไร มันไม่มีความหมายของตัวเองและเข้ารหัสข้อมูลที่ไม่พบแยกต่างหากในคอลัมน์อื่น ๆ ที่กำหนดไว้อย่างถูกต้อง ไม่ควรเลือกหรือใช้
ดังนั้นเรื่องราวของฉันคือว่านี่ไม่ใช่ตัวแทน NULL และฉันก็เกาะติดมัน! เนื่องจากเราไม่ต้องการค่าที่ไม่ใช่ค่า NULL เพื่อจุดประสงค์อื่นนอกเหนือจากการหลอกลวงUNIQUE
ดัชนีให้ละเว้นค่า NULL กรณีการใช้งานของเราไม่มีปัญหาที่เกิดขึ้นกับการสร้าง NULL ตัวแทน
ทั้งหมดที่กล่าวว่าผมมีปัญหากับการใช้มุมมองการจัดทำดัชนีไม่มีแทน SCHEMABINDING
แต่จะนำปัญหาบางอย่างกับมันเช่นความต้องการของการใช้ ขอให้สนุกเพิ่มคอลัมน์ใหม่ลงในตารางฐานของคุณ (อย่างน้อยที่สุดคุณจะต้องวางดัชนีแล้วปล่อยมุมมองหรือเปลี่ยนมุมมองเพื่อไม่ให้ถูกผูกสคีมา) ดูแบบเต็มรูปแบบ (ยาว) รายการของข้อกำหนดสำหรับการสร้างมุมมองที่จัดทำดัชนีใน SQL Server (2005) (หรือรุ่นที่ใหม่กว่า) (2000)
ปรับปรุง
หากคอลัมน์ของคุณเป็นตัวเลขอาจมีความท้าทายในการตรวจสอบให้แน่ใจว่าข้อ จำกัด ที่ไม่ซ้ำใครใช้Coalesce
ไม่ส่งผลให้เกิดการชน ในกรณีนั้นมีตัวเลือกบางอย่าง หนึ่งอาจใช้จำนวนลบเพื่อวาง "ตัวแทน NULLs" เฉพาะในช่วงลบและ "ค่าจริง" เฉพาะในช่วงบวก อีกวิธีหนึ่งคือสามารถใช้รูปแบบต่อไปนี้ ในตารางIssue
(ที่IssueID
เป็นPRIMARY KEY
) มีอาจจะหรืออาจจะไม่ได้เป็นTicketID
แต่ถ้ามีก็จะต้องไม่ซ้ำกัน
ALTER TABLE dbo.Issue ADD TicketUnique
AS (CASE WHEN TicketID IS NULL THEN IssueID END);
ALTER TABLE dbo.Issue ADD CONSTRAINT UQ_Issue_Ticket_AllowNull
UNIQUE (TicketID, TicketUnique);
ถ้า IssueID 1 มีตั๋ว 123 UNIQUE
ข้อ จำกัด จะเป็นค่า (123, NULL) ถ้า IssueID 2 ไม่มีตั๋วมันจะเปิดใช้งาน (NULL, 2) ความคิดบางอย่างจะแสดงให้เห็นว่าข้อ จำกัด นี้ไม่สามารถทำซ้ำสำหรับแถวใด ๆ ในตารางและยังอนุญาตให้มี NULL หลายตัว