ตรวจสอบข้อ จำกัด เพียงหนึ่งในสามคอลัมน์ที่ไม่ใช่ค่าว่าง


61

ฉันมีตาราง (SQL Server) ที่มีผลลัพธ์ 3 ประเภท: FLOAT, NVARCHAR (30) หรือ DATETIME (3 คอลัมน์แยกกัน) ฉันต้องการตรวจสอบให้แน่ใจว่าสำหรับแถวใดก็ตามมีเพียงหนึ่งคอลัมน์เท่านั้นที่มีผลลัพธ์และคอลัมน์อื่น ๆ เป็น NULL ข้อ จำกัด การตรวจสอบที่ง่ายที่สุดในการบรรลุสิ่งนี้คืออะไร?

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

อัปเดต: ขออภัยประเภทข้อมูล snafu น่าเศร้าที่ฉันไม่ได้ตั้งใจชนิดของผลลัพธ์ที่บ่งบอกว่าถูกตีความว่าเป็นประเภทข้อมูล SQL Server เพียงแค่คำศัพท์ทั่วไปได้รับการแก้ไขแล้ว

คำตอบ:


72

ต่อไปนี้ควรทำเคล็ดลับ:

CREATE TABLE MyTable (col1 FLOAT NULL, col2 NVARCHAR(30) NULL, col3 DATETIME NULL);
GO

ALTER TABLE MyTable
ADD CONSTRAINT CheckOnlyOneColumnIsNull
CHECK 
(
    ( CASE WHEN col1 IS NULL THEN 0 ELSE 1 END
    + CASE WHEN col2 IS NULL THEN 0 ELSE 1 END
    + CASE WHEN col3 IS NULL THEN 0 ELSE 1 END
    ) = 1
)
GO

24

คุณอาจต้องทำการทดสอบสามครั้งภายในข้อ จำกัด หนึ่งการทดสอบสำหรับแต่ละคู่ที่คุณต้องการให้เป็นโมฆะและอีกหนึ่งการทดสอบสำหรับคอลัมน์ที่ไม่ควรเป็นโมฆะ:

ALTER TABLE table
ADD CONSTRAINT CK_one_is_null
CHECK (
     (col1 IS NOT NULL AND col2 IS NULL AND col3 IS NULL)
  OR (col2 IS NOT NULL AND col1 IS NULL AND col3 IS NULL) 
  OR (col3 IS NOT NULL AND col1 IS NULL AND col2 IS NULL)
);

นี่ไม่ใช่ขนาดที่ปรับขนาดได้ฉันมีตารางที่มีกุญแจต่างประเทศ 9 อันและมีเพียงอันเดียวที่ควรจะไม่ว่างฉันชอบวิธีการแก้ปัญหาของ
@MarkStoreySmith

5

นี่คือโซลูชัน PostgreSQL ที่ใช้ฟังก์ชันอาร์เรย์ในตัว :

ALTER TABLE your_table
ADD chk_only_one_is_not_null CHECK (array_length(array_remove(ARRAY[col1::text, col2::text, col3::text], NULL), 1) = 1);

สิ่งนี้จะเป็นการใช้งานได้เร็วขึ้นใน postgreSQL มากกว่าโซลูชั่น CASE หรือ AND / OR ที่กล่าวถึงก่อนหน้านี้ซึ่งโพสต์โดย Mark Storey และ mrdenny ตามลำดับหรือไม่
Chris Britt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.