2014-03-04 100 views
0

地址表爲兩個公司和聯繫人共享。我有一個限制,阻止用戶添加公司ID和聯繫人ID的記錄。我試圖添加另一個約束,使每個公司ID或聯繫人ID只有1個活動(ACTIVE FLAG ='TRUE')地址。但我希望能夠無限制地無效(ACTIVE FLAG ='FALSE')。每個ID一個有效記錄

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

您要添加的約束的積極=真正的'和「積極=假」爲Contact ID和公司ID的兩個組合,所以這是一個同義反復,你不妨刪除此約束。 我相信強制執行規則的唯一方法是「只有一個活動標誌,0到很多非活動狀態」是由觸發器執行的。

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

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;