MySQL hỗ trợ chức năng các bộ phận chính kể từ 8.0.13 .
-
Nếu phiên bản của bạn đủ mới, bạn có thể xác định chỉ mục của mình là:
UNIQUE(`user_id`, `test_id`, (IFNULL(`completed_date`, -1)))
( Bản trình diễn trên dbfiddle.uk )
Lưu ý rằng chỉ mục trên cũng sẽ ngăn ngày trùng lặp cho các lần thực thi đã hoàn thành. Nếu những điều đó phải hợp lệ thì chỉ mục được sửa đổi một chút sẽ hoạt động:
UNIQUE(`user_id`, `test_id`, ( CASE WHEN `completed_date` IS NOT NULL THEN NULL ELSE 0 END))
( Bản trình diễn trên dbfiddle.uk )
Mặc dù sau đó nó bắt đầu cảm thấy hơi bẩn;)
-
Nếu bạn có ít nhất phiên bản 5.7 bạn có thể sử dụng một (ảo) cột được tạo như một giải pháp thay thế:
CREATE TABLE `executed_tests` ( `id` INTEGER AUTO_INCREMENT NOT NULL, `user_id` INTEGER NOT NULL, `test_id` INTEGER NOT NULL, `start_date` DATE NOT NULL, `completed_date` DATE, `_helper` CHAR(11) AS (IFNULL(`completed_date`, -1)), PRIMARY KEY (`id`), UNIQUE(`user_id`, `test_id`, `_helper`) );
-
Nếu bạn bị kẹt trên 5.6 sau đó là sự kết hợp của cột thông thường (không ảo) và
INSERT
được sửa đổi một chút các câu lệnh sẽ hoạt động:CREATE TABLE `executed_tests` ( `id` INTEGER AUTO_INCREMENT NOT NULL, `user_id` INTEGER NOT NULL, `test_id` INTEGER NOT NULL, `start_date` DATE NOT NULL, `completed_date` DATE, `is_open` BOOLEAN, PRIMARY KEY (`id`), UNIQUE(`user_id`, `test_id`, `is_open`) );
Trong trường hợp này, bạn sẽ đặt
is_open
thànhtrue
để thực thi không đầy đủ vàNULL
sau khi hoàn thành, sử dụng thực tế là haiNULL
s được coi là không bình đẳng.