Selain solusi pemicu yang bagus dari @Rolando, ada solusi lain dari masalah ini di MySQL (sampai CHECK
kendala diimplementasikan).
Cara meniru beberapa CHECK
kendala di MySQL
Jadi, jika Anda lebih suka kendala integritas referensial dan ingin menghindari pemicu (karena masalah di MySQL ketika Anda memiliki keduanya di tabel Anda), Anda dapat menggunakan tabel referensi kecil lainnya:
CREATE TABLE age_allowed
( age TINYINT UNSIGNED NOT NULL
, PRIMARY KEY (age)
) ENGINE = InnoDB ;
Isi dengan 20 baris:
INSERT INTO age_allowed
(age)
VALUES
(0), (1), (2), (3), ..., (19) ;
Maka meja Anda adalah:
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 ;
Anda harus menghapus akses tulis ke age_allowed
tabel, untuk menghindari penambahan atau penghapusan baris yang tidak disengaja.
Trik ini tidak akan berfungsi dengan FLOAT
kolom tipe data, sayangnya (terlalu banyak nilai di antara 0.0
dan 20.0
).
Bagaimana cara meniru CHECK
batasan arbitrer di MySQL (5.7) dan MariaDB (dari 5.2 hingga 10.1)
Karena MariaDB menambahkan kolom yang dihitung dalam versi 5.2 mereka (rilis GA: 2010-11-10 ) dan MySQL di 5,7 (rilis GA: 2015-10-21 ) - yang mereka sebut VIRTUAL
dan GENERATED
masing-masing - yang dapat bertahan, yaitu disimpan dalam tabel - mereka memanggil mereka PERSISTENT
dan STORED
masing-masing - kita dapat menggunakannya untuk menyederhanakan solusi di atas dan bahkan lebih baik, memperluasnya untuk meniru / menegakkan CHECK
batasan sewenang-wenang ):
Seperti di atas, kita akan membutuhkan tabel bantuan tetapi dengan satu baris kali ini yang akan bertindak sebagai tabel "jangkar". Bahkan lebih baik, tabel ini dapat digunakan untuk sejumlah CHECK
kendala.
Kami kemudian menambahkan kolom yang dihitung yang mengevaluasi ke salah satu TRUE
/ FALSE
/ UNKNOWN
, persis seperti CHECK
batasan - - kolom ini memiliki FOREIGN KEY
kendala untuk tabel jangkar kami. Jika kondisi / kolom dievaluasi menjadiFALSE
untuk beberapa baris, baris ditolak, karena FK.
Jika kondisi / kolom mengevaluasi ke TRUE
atau UNKNOWN
( NULL
), baris tidak ditolak, persis seperti yang seharusnya terjadi dengan CHECK
kendala:
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 ;
Contohnya adalah untuk versi MySQL 5.7. Di MariaDB (versi 5.2+ hingga 10.1), kita hanya perlu memodifikasi sintaks dan mendeklarasikan kolom sebagai PERSISTENT
gantinya STORED
. Dalam versi 10.2 yangSTORED
kata kunci ditambahkan juga, jadi contoh di atas berfungsi dalam kedua rasa (MySQL dan MariaDB) untuk versi terbaru.
Jika kita ingin menegakkan banyak CHECK
kendala (yang umum dalam banyak desain), kita hanya perlu menambahkan kolom yang dihitung dan kunci asing untuk masing-masing dari mereka. Kami hanya perlu satu truth
tabel dalam database. Seharusnya satu baris dimasukkan dan kemudian semua akses tulis dihapus.
Namun dalam MariaDB terbaru, kita tidak perlu melakukan semua akrobat ini lagi, karena CHECK
kendala telah diterapkan di versi 10.2.1 (rilis alpha: 2016-Jul-04)!
Versi 10.2.2 saat ini masih merupakan versi beta tetapi tampaknya fitur tersebut akan tersedia dalam rilis stabil pertama dari seri MariaDB 10.2.