นอกจากโซลูชันทริกเกอร์ที่ดีโดย @Rolando ยังมีวิธีแก้ไขปัญหาอื่นใน MySQL (จนกว่าCHECK
จะมีการบังคับใช้ข้อ จำกัด )
วิธีเลียนแบบCHECK
ข้อ จำกัดบางอย่างใน MySQL
ดังนั้นหากคุณต้องการข้อ จำกัด ของ Referential Integrity และต้องการหลีกเลี่ยงทริกเกอร์ (เนื่องจากปัญหาใน MySQL เมื่อคุณมีทั้งคู่ในตารางของคุณ) คุณสามารถใช้ตารางอ้างอิงขนาดเล็กอื่น:
CREATE TABLE age_allowed
( age TINYINT UNSIGNED NOT NULL
, PRIMARY KEY (age)
) ENGINE = InnoDB ;
เติมด้วย 20 แถว:
INSERT INTO age_allowed
(age)
VALUES
(0), (1), (2), (3), ..., (19) ;
จากนั้นตารางของคุณจะเป็น:
CREATE TABLE test
( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT
, age TINYINT UNSIGNED NOT NULL
, PRIMARY KEY (id)
, CONSTRAINT age_allowed__in__test
FOREIGN KEY (age)
REFERENCES age_allowed (age)
) ENGINE = InnoDB ;
คุณจะต้องลบสิทธิ์การเขียนลงในage_allowed
ตารางเพื่อหลีกเลี่ยงการเพิ่มหรือลบแถวโดยไม่ตั้งใจ
เคล็ดลับนี้จะไม่ทำงานกับFLOAT
คอลัมน์ประเภทข้อมูลโชคไม่ดี (ค่ามากเกินไประหว่าง0.0
และ20.0
)
วิธีจำลองCHECK
ข้อ จำกัดโดยพลการใน MySQL (5.7) และ MariaDB (จาก 5.2 ถึง 10.1)
เนื่องจากMariaDB เพิ่มคอลัมน์ที่คำนวณแล้วในเวอร์ชัน 5.2 (GA รีลีส: 2010-11-10 ) และ MySQL ในรุ่น 5.7 (รุ่น GA: 2015-10-21 ) - ซึ่งพวกเขาเรียกพวกเขาVIRTUAL
และGENERATED
ตามลำดับ - ที่สามารถคงอยู่เช่นเก็บไว้ใน ตาราง - พวกเขาเรียกพวกเขาPERSISTENT
และSTORED
ตามลำดับ - เราสามารถใช้พวกเขาเพื่อทำให้การแก้ปัญหาข้างต้นง่ายขึ้นและดียิ่งขึ้นขยายไปเพื่อจำลอง / บังคับใช้CHECK
ข้อ จำกัดโดยพลการ ):
ดังกล่าวข้างต้นเราจะต้องมีตารางความช่วยเหลือ แต่มีแถวเดียวในเวลานี้ที่จะทำหน้าที่เป็นตาราง "ยึด" ยิ่งไปกว่านั้นตารางนี้สามารถใช้กับCHECK
ข้อ จำกัดจำนวนเท่าใดก็ได้
จากนั้นเราเพิ่มคอลัมน์ที่คำนวณซึ่งประเมินเป็นTRUE
/ FALSE
/ UNKNOWN
ตามที่กำหนดแน่นอนCHECK
- แต่คอลัมน์นี้มีFOREIGN KEY
ข้อ จำกัด ในตารางจุดยึดของเรา หากเงื่อนไข / คอลัมน์ประเมินค่าFALSE
สำหรับบางแถวแถวนั้นจะถูกปฏิเสธเนื่องจาก FK
หากเงื่อนไข / คอลัมน์ประเมินเป็น TRUE
หรือUNKNOWN
( NULL
) แถวจะไม่ถูกปฏิเสธตรงตามที่ควรจะเกิดขึ้นกับCHECK
ข้อ จำกัด :
CREATE TABLE truth
( t BIT NOT NULL,
PRIMARY KEY (t)
) ENGINE = InnoDB ;
-- Put a single row:
INSERT INTO truth (t)
VALUES (TRUE) ;
-- Then your table would be:
-- (notice the change to `FLOAT`, to prove that we don't need)
-- (to restrict the solution to a small type)
CREATE TABLE test
( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
age FLOAT NOT NULL,
age_is_allowed BIT -- GENERATED ALWAYS
AS (age >= 0 AND age < 20) -- our CHECK constraint
STORED,
PRIMARY KEY (id),
CONSTRAINT check_age_must_be_non_negative_and_less_than_20
FOREIGN KEY (age_is_allowed)
REFERENCES truth (t)
) ENGINE = InnoDB ;
ตัวอย่างนี้ใช้สำหรับ MySQL 5.7 เวอร์ชัน ใน MariaDB (รุ่น 5.2+ ถึง 10.1) เราก็ต้องปรับเปลี่ยนไวยากรณ์และประกาศคอลัมน์เป็นแทนPERSISTENT
STORED
ในเวอร์ชัน 10.2 มีการSTORED
เพิ่มคำหลักเช่นกันดังนั้นตัวอย่างข้างต้นสามารถใช้ได้กับทั้งรสชาติ (MySQL และ MariaDB) สำหรับเวอร์ชันล่าสุด
หากเราต้องการบังคับใช้CHECK
ข้อ จำกัดจำนวนมาก(ซึ่งเป็นเรื่องปกติในการออกแบบจำนวนมาก) เราเพียงแค่ต้องเพิ่มคอลัมน์ที่คำนวณและคีย์ต่างประเทศสำหรับแต่ละข้อ เราต้องการเพียงหนึ่งtruth
ตารางในฐานข้อมูล ควรแทรกหนึ่งแถวจากนั้นสิทธิ์การเขียนทั้งหมดจะถูกลบ
อย่างไรก็ตามใน MariaDB ล่าสุดเราไม่จำเป็นต้องทำการแสดงผาดโผนทั้งหมดอีกต่อไปเช่น CHECK
มีการใช้งานข้อ จำกัดในเวอร์ชัน 10.2.1 (ปล่อยอัลฟ่า: 2016-Jul-04)!
เวอร์ชั่น 10.2.2 ปัจจุบันยังคงเป็นรุ่นเบต้า แต่ดูเหมือนว่าคุณสมบัติดังกล่าวจะมีอยู่ในซีรีย์ MariaDB 10.2 ที่เสถียรรุ่นแรก