结合独特约束的软删除解决方案?

Solution for softdeletes in combination with unique constraints?

我有一个 table 订单,包含 external_idshop_iddeleted_at 列。为确保 external_idshop_id 的组合是唯一的,我对这 3 列设置了唯一约束。

这是因为我们不计算软删除值的唯一性,因此如果 deleted_at 等于 Laravel 中的 NULL 它不是软删除的,但在任何其他情况下都是,这使得可能有多个软删除记录。示例:

external_id        |shop_id   |deleted_at         |
-------------------|----------|-------------------|
1                  |         5|             [NULL]| <-- should be unique
1                  |         5|2019-12-19 13:45:22|
1                  |         5|2019-12-19 13:35:45|

除了 1 个警告外,这听起来不错:MySQL 不强制 NULL 值的唯一性,这对于它的工作很重要。通常 the workaround 是将可为空的默认值更改为空字符串。然而 deleted_at 是一个时间戳。

create table orders (external_id int, shop_id int, deleted_at timestamp);
ALTER TABLE orders 
ADD COLUMN `n_deleted_at` timestamp AS (COALESCE(deleted_at, '1980-01-01')) VIRTUAL;
CREATE UNIQUE INDEX idx ON orders (external_id, shop_id, n_deleted_at);
INSERT INTO orders (external_id, shop_id, deleted_at) VALUES (1, 5, NULL);
INSERT INTO orders (external_id, shop_id, deleted_at) VALUES (1, 5, '2019-12-19 13:45:2');
INSERT INTO orders (external_id, shop_id, deleted_at) VALUES (1, 5, '2019-12-19 13:35:45');
INSERT INTO orders (external_id, shop_id, deleted_at) VALUES (1, 5, '2019-12-19 13:35:45');
Duplicate entry '1-5-2019-12-19 13:35:45' for key 'orders.idx'
INSERT INTO orders (external_id, shop_id, deleted_at) VALUES (1, 5, NULL);
Duplicate entry '1-5-1980-01-01 00:00:00' for key 'orders.idx'

db<>fiddle here