อนุญาตเฉพาะค่าบางค่าในคอลัมน์ B ตามค่าของคอลัมน์ A

ฉันต้องการอนุญาตให้แทรกค่าตามจำนวนที่กำหนดลงในคอลัมน์ A และอนุญาตให้แทรกค่าเพียงจำนวนหนึ่งลงในคอลัมน์ B ทั้งนี้ขึ้นอยู่กับค่าที่ป้อน ตัวอย่างเช่น

ตัวอย่างเช่น

  • ถ้า A = 1, B สามารถอยู่ระหว่าง 1 ถึง 9
  • ถ้า A = 2, B สามารถอยู่ระหว่าง 10 ถึง 19
  • ถ้า A = 3, B สามารถอยู่ระหว่าง 20 ถึง 29

ฉันจะบรรลุเป้าหมายนี้ได้อย่างไร?

ฉันคิดว่าข้อจำกัดในการตรวจสอบเป็นจุดเริ่มต้นที่ดีที่สุด ข้อจำกัดง่ายๆ จะทำให้แน่ใจได้ว่าสามารถเพิ่มได้เฉพาะค่า 1-3 ลงในคอลัมน์ A เช่น:

CREATE TABLE dbo.test (
    col_a INT, 
    col_b INT,
    CONSTRAINT ch_col_a_valid_range CHECK (col_a BETWEEN 1 AND 3)
)
GO

จากนั้นฉันก็สรุปได้ว่าการใช้ฟังก์ชันสเกลาร์เพื่อตรวจสอบว่า col_b ถูกต้องหรือไม่ โดยส่งค่าจาก col_a และ col_b

CREATE FUNCTION dbo.value_is_valid (
    @a INT, 
    @b INT
)
RETURNS BIT
AS 
BEGIN
    IF (@a = 1 AND @b BETWEEN 1 AND 9) RETURN 1;
    IF (@a = 2 AND @b BETWEEN 10 AND 19) RETURN 1;
    IF (@a = 3 AND @b BETWEEN 20 AND 29) RETURN 1;
    RETURN 0;
END
GO

จากนั้นเพิ่มข้อจำกัดลงในตาราง และเรียกใช้ฟังก์ชันซึ่งเป็นส่วนหนึ่งของการตรวจสอบ

CREATE TABLE dbo.test (
    col_a INT, 
    col_b INT,
    CONSTRAINT ch_col_a_valid_range CHECK (col_a BETWEEN 1 AND 3),
    CONSTRAINT ch_col_b_valid_based_on_a CHECK(dbo.value_is_valid(col_a, col_b) = 1)
)
GO

อย่างไรก็ตาม การแทรกต่อไปนี้ล้มเหลว โดยบ่นเกี่ยวกับข้อขัดแย้งกับข้อจำกัด ch_col_b_valid_based_on_a ที่เพิ่มเข้ามา

INSERT INTO dbo.test (
    col_a, 
    col_b
)
VALUES (1, 9)

คำสั่ง INSERT ขัดแย้งกับข้อจำกัด CHECK "ch_col_b_valid_based_on_a" ข้อขัดแย้งเกิดขึ้นในฐานข้อมูล " MyDB", ตาราง "dbo.test"

ฉันจะทำอย่างไรเพื่อแก้ไขปัญหานี้และบรรลุผลตามที่กล่าวข้างต้น


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


person Klicker    schedule 18.04.2019    source แหล่งที่มา


คำตอบ (2)


วิธีหนึ่งคือข้อจำกัด check:

CREATE TABLE dbo.test (
    col_a INT, 
    col_b INT,
    CONSTRAINT ch_col_a_valid_range CHECK (col_a BETWEEN 1 AND 3),
    CONSTRAINT chk_col_a_colb
        CHECK ( (col_a = 1 AND col_b BETWEEN 1 AND 9) OR
                (col_a = 2 AND col_b BETWEEN 10 AND 19) OR
                (col_a = 3 AND col_b BETWEEN 20 AND 29)
             )

);

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

person Gordon Linoff    schedule 18.04.2019
comment
ปัญหาเกี่ยวกับข้อจำกัดในการตรวจสอบคือ เมื่อแทรกค่าลงในทั้ง col_a และ col_b จะไม่ทำงาน วิธีเดียวที่จะแก้ไขปัญหานี้ เท่าที่ฉันสามารถบอกได้คือการแทรกลงใน col_a ในธุรกรรมหนึ่ง จากนั้นจึงแทรกลงใน col_b ในอีกธุรกรรมหนึ่ง แต่นี่ยังห่างไกลจากอุดมคติ ฉันชอบอุดมคติของคุณในการคงความสัมพันธ์ FK ไว้กับตารางตัวเลือก ที่ถูกต้อง นั่นอาจทำงานได้ดี - person Klicker; 19.04.2019
comment
จริงๆ แล้ว ความคิดเห็นของฉันไม่ถูกต้อง - วิธีตรวจสอบข้อจำกัดนี้ ใช้ ได้ผล และตัวอย่างในความคิดเห็นต้นฉบับของฉัน ใช้ ได้ผล - person Klicker; 19.04.2019

คุณสามารถใช้คณิตศาสตร์เพื่อสร้างข้อจำกัดที่ง่ายกว่าได้

CREATE TABLE dbo.test (
    col_a INT, 
    col_b INT,
    CONSTRAINT ch_col_a_valid_range CHECK (col_a BETWEEN 1 AND 3),
    CONSTRAINT ch_col_b_valid_based_on_a CHECK(col_b/10 + 1 = col_a)
);
person Luis Cazares    schedule 18.04.2019