Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Einschränkung mit bedingter Wertprüfung in MySQL

Gemäß der Dokumentation ,

Also not null entfernen -constraint von Status und Hinzufügen eines eindeutigen Index zu (ContactId,PhoneId,Status) funktioniert wie gewünscht, wenn Sie null verwenden statt 0 für inaktiv Aufzeichnungen.

Wenn Sie null nicht verwenden möchten oder können für Ihren Status Spalte sicherstellen möchten, dass beide Status=0 sind und Status=null sich gleich verhalten, oder z.B. Status=2 behandeln möchten als aktiv (und Eindeutigkeit erzwingen) können Sie auch eine Dummy-Spalte hinzufügen, die aus Status berechnet wird .

Wenn Sie MySQL 5.7+ verwenden, können Sie dies mit einer generierten Spalte tun:

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 

Andernfalls können Sie eine normale Spalte verwenden und Trigger verwenden, um den Wert der Spalte zu berechnen, z. B.:

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);

Sie können die Formel natürlich umstellen auf z.B. if(new.Status <> 0, new.Status, null); wenn Sie unterschiedliche Werte für Status zulassen möchten zu.