地址表是为公司和联系人共享的。我有一个约束,阻止用户添加包含公司ID和联系人ID的记录。我正在尝试添加另一个约束,使每个公司ID或联系人ID只有1个活动(ACTIVE FLAG ='TRUE')地址。但我希望能够无限制地无效(ACTIVE FLAG ='FALSE')。
ALTER TABLE [dbo].[ADDRESSES] WITH CHECK ADD CONSTRAINT [chk_ONLY_ONE_ACTIVE_ADDRESS] CHECK (([COMPANY_ID] IS NOT NULL AND [CONTACT_ID] IS NULL AND [ACTIVE] = 'TRUE' OR [COMPANY_ID] IS NULL AND [CONTACT_ID] IS NOT NULL AND [ACTIVE] = 'TRUE' OR [COMPANY_ID] IS NULL AND [CONTACT_ID] IS NOT NULL AND [ACTIVE] = 'FALSE' OR [COMPANY_ID] IS NOT NULL AND [CONTACT_ID] IS NULL AND [ACTIVE] = 'FALSE'))
GO
我错过了哪里?
由于 jlimited
答案 0 :(得分:0)
您正在为联系人ID和公司ID的两种组合添加约束“active = true”和“active = false”,因此它是一个重言式,您也可以删除此约束。 我认为强制执行规则的唯一方法是“只有一个活动标志,0到多个非活动标志”是触发器。
答案 1 :(得分:0)
感谢Jayvee的回复。这是我想出的解决方案。
我首先创建了两个函数......
一
CREATE FUNCTION [dbo].[fnCheckForActiveContactAddress](
@id int
)
RETURNS INT
AS
BEGIN
DECLARE @result INT
IF @id IS NOT NULL
SET @result = ISNULL((select count(*) from dbo.Addresses where CONTACT_ID = @ID AND ACTIVE = 'TRUE'),0)
ELSE
SET @result = 1
RETURN @result
END
GO
两个
CREATE FUNCTION [dbo].[fnCheckForActiveCompanyAddress](
@id int
)
RETURNS INT
AS
BEGIN
DECLARE @result INT
If @id IS NOT NULL
SET @result = ISNULL((select count(*) from dbo.Addresses where COMPANY_ID = @ID AND ACTIVE = 'TRUE'),0)
ELSE
SET @result = 1
RETURN @result
END
GO
然后我添加了以下约束......
ALTER TABLE [dbo].[ADDRESSES] WITH CHECK ADD CONSTRAINT [chk_COMPANY_OR_CONTACT] CHECK (([COMPANY_ID] IS NOT NULL AND [CONTACT_ID] IS NULL OR [COMPANY_ID] IS NULL AND [CONTACT_ID] IS NOT NULL))
GO
ALTER TABLE [dbo].[ADDRESSES] WITH NOCHECK ADD CONSTRAINT [CHK_ADDRESSES_ONLY_ONE_ACTIVE_CONTACT] CHECK (([dbo].[fnCheckForActiveContactAddress]([CONTACT_ID])=(1)))
GO
ALTER TABLE [dbo].[ADDRESSES] WITH NOCHECK ADD CONSTRAINT [CHK_ADDRESSES_ONLY_ONE_ACTIVE_COMPANY] CHECK (([dbo].[fnCheckForActiveCompanyAddress]([COMPANY_ID])=(1)))
GO
此解决方案似乎运作良好。
有关改善它的想法吗?
jlimited
答案 2 :(得分:0)
如果我理解您的要求,这应该有效(如果-1不是有效的CompanyID或ContactID):
create table T (
CompanyID int,
ContactID int,
BothIDs as
CASE WHEN CompanyID IS NOT NULL and ContactID IS NOT NULL
THEN 1 ELSE 0 END PERSISTED
check (BothIDs = 0),
ActiveFlag varchar(5) check (ActiveFlag in ('TRUE','FALSE')),
ActiveCheck as
CASE WHEN ActiveFlag='TRUE' then -1 ELSE COALESCE(CompanyID,ContactID) END,
unique (ActiveCheck)
);
insert into T values
(1,NULL,'FALSE'),
(NULL,2,'FALSE'),
(3,NULL,'TRUE'),
(4,NULL,'FALSE');
GO
UPDATE T SET
ActiveFlag = 'TRUE'
WHERE CompanyID = 4;