在 MySQL 中使用条件值检查进行约束
Constrain with conditional value check in MySQL
我需要添加基于组合和值的约束检查
我的 Table 结构是
CREATE TABLE IF NOT EXISTS `ContactPhone` (
`ContactPhoneId` int(10) unsigned NOT NULL,
`ContactId` int(11) NOT NULL,
`PhoneId` smallint(5) unsigned NOT NULL,
`Status` tinyint(1) NOT NULL DEFAULT '1'
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `ContactPhone`
--
ALTER TABLE `ContactPhone`
ADD PRIMARY KEY (`ContactPhoneId`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `ContactPhone`
--
ALTER TABLE `ContactPhone`
MODIFY `ContactPhoneId` int(10) unsigned NOT NULL
AUTO_INCREMENT,AUTO_INCREMENT=1;
我需要根据以下组合条件约束来确保记录
ContactId
PhoneId
Status == 1
(值应为 1 - Active Record)
注意:不需要非活动记录(即 Status == 0
)。我只需要对 Active Records 进行此约束。
请帮助我如何为上述提议添加此约束 MySQL Table。
根据 documentation、
A UNIQUE index permits multiple NULL values for columns that can contain NULL.
因此,如果您使用 null
而不是0
无效 条记录。
如果您不想或不能为您的 Status
列使用 null
,请确保 Status=0
和 Status=null
的行为相同,或者例如也想将 Status=2
视为 active(并强制执行唯一性),您可以添加一个虚拟列,该列将从 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
的不同值。
我需要添加基于组合和值的约束检查
我的 Table 结构是
CREATE TABLE IF NOT EXISTS `ContactPhone` (
`ContactPhoneId` int(10) unsigned NOT NULL,
`ContactId` int(11) NOT NULL,
`PhoneId` smallint(5) unsigned NOT NULL,
`Status` tinyint(1) NOT NULL DEFAULT '1'
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `ContactPhone`
--
ALTER TABLE `ContactPhone`
ADD PRIMARY KEY (`ContactPhoneId`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `ContactPhone`
--
ALTER TABLE `ContactPhone`
MODIFY `ContactPhoneId` int(10) unsigned NOT NULL
AUTO_INCREMENT,AUTO_INCREMENT=1;
我需要根据以下组合条件约束来确保记录
ContactId
PhoneId
Status == 1
(值应为 1 - Active Record)
注意:不需要非活动记录(即 Status == 0
)。我只需要对 Active Records 进行此约束。
请帮助我如何为上述提议添加此约束 MySQL Table。
根据 documentation、
A UNIQUE index permits multiple NULL values for columns that can contain NULL.
因此,如果您使用 null
而不是0
无效 条记录。
如果您不想或不能为您的 Status
列使用 null
,请确保 Status=0
和 Status=null
的行为相同,或者例如也想将 Status=2
视为 active(并强制执行唯一性),您可以添加一个虚拟列,该列将从 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
的不同值。