Съгласно документацията ,
Така че премахването на not null
-ограничение от Status
и добавяне на уникален индекс към (ContactId,PhoneId,Status)
ще работи както искате, ако използвате null
вместо 0
за неактивен записи.
Ако не искате или не можете да използвате null
за вашето Status
колона, искам да се уверите, че и двете Status=0
и Status=null
се държат идентично, или напр. искате да третирате Status=2
като активен (и налагане на уникалност) също, можете да добавите фиктивна колона, която ще се изчислява от Status
.
Ако използвате MySQL 5.7+, можете да направите това с генерирана колона:
CREATE TABLE IF NOT EXISTS `ContactPhone` (
`ContactPhoneId` int(10) unsigned NOT NULL auto_increment primary key,
`ContactId` int(11) NOT NULL,
`PhoneId` smallint(5) unsigned NOT NULL,
`Status` tinyint(1) NOT NULL DEFAULT '1',
`StatusUnq` tinyint(1) as (if(Status <> 0, 1, null)) stored null,
constraint unique (ContactId, PhoneId, StatusUnq)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
insert into ContactPhone (ContactPhoneId, ContactId, PhoneId, Status)
values (1, 1, 1, 1);
insert into ContactPhone (ContactPhoneId, ContactId, PhoneId, Status)
values (2, 1, 1, 1);
-- Duplicate key error
insert into ContactPhone (ContactPhoneId, ContactId, PhoneId, Status)
values (3, 1, 1, 0);
insert into ContactPhone (ContactPhoneId, ContactId, PhoneId, Status)
values (4, 1, 1, 0);
update ContactPhone set Status = 1 where ContactPhoneId = 4;
-- Duplicate key error
В противен случай можете да използвате нормална колона и да използвате тригери, за да изчислите стойността на колоната, напр.:
create trigger trbi_contactPhoneUnique before insert on ContactPhone
for each row
set new.StatusUnq = if(new.Status <> 0, 1, null);
create trigger trbu_contactPhoneUnique before update on ContactPhone
for each row
set new.StatusUnq = if(new.Status <> 0, 1, null);
Разбира се, можете да превключите формулата на напр. if(new.Status <> 0, new.Status, null);
ако искате да разрешите различни стойности на Status
също.