触发器是按照您的要求进行操作的传统方式。这是一个简单的演示;
--if object_id('member') is not null drop table member
go
create table member (
idMember INT Identity Primary Key,
memEmail varchar(100),
memEmailPartner varchar(100)
)
go
create trigger trg_member on member after insert, update as
begin
set nocount on
if exists (select 1 from member m join inserted i on i.memEmail = m.memEmail and i.idMember <> m.idMember) or
exists (select 1 from member m join inserted i on i.memEmail = m.memEmailPartner and i.idMember <> m.idMember) or
exists (select 1 from member m join inserted i on i.memEmailPartner = m.memEmail and i.idMember <> m.idMember) or
exists (select 1 from member m join inserted i on i.memEmailPartner = m.memEmailPartner and i.idMember <> m.idMember)
begin
raiserror('Email addresses must be unique.', 16, 1)
rollback
end
end
go
insert member(memEmail, memEmailPartner) values('a@a.com', null), ('b@b.com', null), (null, 'c@c.com'), (null, 'd@d.com')
go
select * from member
insert member(memEmail, memEmailPartner) values('a@a.com', null) -- should fail
go
insert member(memEmail, memEmailPartner) values(null, 'a@a.com') -- should fail
go
insert member(memEmail, memEmailPartner) values('c@c.com', null) -- should fail
go
insert member(memEmail, memEmailPartner) values(null, 'c@c.com') -- should fail
go
insert member(memEmail, memEmailPartner) values('e@e.com', null) -- should work
go
insert member(memEmail, memEmailPartner) values(null, 'f@f.com') -- should work
go
select * from member
-- Make sure updates still work!
update member set memEmail = memEmail, memEmailPartner = memEmailPartner
我没有对此进行过广泛的测试,但如果你想尝试这种方法,它应该足以让你开始。
StuartLC 注意到 UDF 检查约束在基于集合的更新和/或各种其他条件下失败的可能性,触发器没有这个问题。
Stuart 还建议重新考虑这是否真的应该是数据库约束或通过其他地方的业务逻辑进行管理。我倾向于同意 - 我的直觉是,迟早你会遇到需要重复使用电子邮件地址的情况,或者以其他方式不是严格唯一的。