sql >> Base de Datos >  >> RDS >> Mysql

Restricción con verificación de valor condicional en MySQL

Según la documentación ,

Entonces eliminando el not null -restricción de Status y agregar un índice único en (ContactId,PhoneId,Status) funcionará como quieras, si usas null en lugar de 0 para inactivo registros.

Si no quiere o no puede usar null para su Status columna, quiere asegurarse de que tanto Status=0 y Status=null comportarse de forma idéntica, o p. desea tratar Status=2 como activo (y haciendo cumplir la unicidad) también, puede agregar una columna ficticia que se calculará a partir de Status .

Si está utilizando MySQL 5.7+, puede hacer esto con una columna generada:

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 

De lo contrario, puede usar una columna normal y usar disparadores para calcular el valor de la columna, por ejemplo:

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

Por supuesto, puede cambiar la fórmula a, p. if(new.Status <> 0, new.Status, null); si desea permitir diferentes valores de Status también.