2011-05-05 63 views
0

我在SQL Server 2008中如何防止一個條目在一個表中現有另一個表

  • 俱樂部3代表與ID的PK和名稱。
  • 有ID的PK,ClubID的FK,名稱,短代碼和關鍵字的產品。
    • 有一個英國強制執行ShortCode /關鍵字組合沒有重複的關鍵字。
  • ProductAdditionalShortCodes。這具有ID的PK,產品ID的FK和關鍵字

我們的想法是,以防止產品的任何短碼/關鍵詞組合,以指向不同的俱樂部,同時也防止重複的短/代碼關鍵字組合的創建

我有一個可以工作的解決方案,但感覺笨重,並且如果多個用戶同時更新多個條目,可能會在某些情況下失敗。 (假設)

如何向數據庫添加某種形式的約束以防止主表中的關鍵字與附加表中的相同並且相反?

以下是一個示例腳本,用於創建場景以及一些我想要阻止的示例。如果改變的影響不會破壞解決方案的其他方面,我並不反對改變DB設計。 (我意識到這是主觀的)

use Tinker 

if exists (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.ProductAdditionalKeywords') AND type in (N'U')) 
    drop table dbo.ProductAdditionalKeywords 
go 
if exists (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.Products') AND type in (N'U')) 
    drop table dbo.Products 
go 
if exists (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.Clubs') AND type in (N'U')) 
    drop table dbo.Clubs 
go 

create table dbo.Clubs (
    ID  int   not null identity(1,1) 
    ,Name  varchar(50) not null 
    ,constraint PK_Clubs primary key clustered (ID) 
) 
go 
alter table dbo.Clubs add constraint UK_Clubs__Name unique (Name) 
go 
create table dbo.Products (
    ID  int   not null identity(1,1) 
    ,ClubID int   not null 
    ,Name  varchar(50) not null 
    ,ShortCode varchar(50) not null 
    ,Keyword varchar(50) not null 
    ,constraint PK_Products primary key clustered (ID) 
) 
go 
alter table dbo.Products add constraint UK_Products__ShortCode_Keyword unique (ShortCode , Keyword) 
go 
alter table dbo.Products add constraint UK_Products__Name unique (Name) 
go 
alter table dbo.Products add constraint FK_Products_ClubID foreign key (ClubID) references dbo.Clubs (ID) 
go 
create table dbo.ProductAdditionalKeywords (
    ID  int   not null identity(1,1) 
    ,ProductID int   not null 
    ,Keyword varchar(50) not null 
    ,constraint PK_ProductAdditionalKeywords primary key clustered (ID) 
) 
go 
alter table dbo.ProductAdditionalKeywords add constraint FK_ProductAdditionalKeywords_ProductID foreign key (ProductID) references dbo.Products (ID) 
go 
alter table dbo.ProductAdditionalKeywords add constraint UK_ProductAdditionalKeywords__Keyword unique (Keyword) 
go 

insert into dbo.Clubs (Name) 
      select 'Club 1' 
union all select 'Club 2' 

insert into dbo.Products (ClubID,Name,Shortcode,Keyword) 
      select 1,'Product 1','001','P1' 
union all select 1,'Product 2','001','P2' 
union all select 1,'Product 3','001','P3' 
union all select 2,'Product 4','002','P4' 
union all select 2,'Product 5','002','P5' 
union all select 2,'Product 6','002','P6' 

insert into dbo.ProductAdditionalKeywords (ProductID,Keyword) 
      select 1,'P1A' 
union all select 1,'P1B' 
union all select 2,'P2A' 
union all select 2,'P2B' 

/* 
What can be done to prevent the following statements from beeing allowed based on the reason in the comments? 
*/ 

--insert into dbo.ProductAdditionalKeywords (ProductID,Keyword) values (1 , 'P2') -- Main keyword for product 2 
--update dbo.Products set Keyword = 'P1A' where ID = 2        -- Additional keyword for product 1 
--insert into dbo.ProductAdditionalKeywords (ProductID,Keyword) values (3 , 'P1') -- Main ShortCode/Keyword combination for product 1 

/* 
At the moment I look at the following view to see if the proposed(new/updated) Keyword/Shortcode combination already exists 
If it already exists I pevent the insert/update 
Is there any way to do it in the DB via constraints rather than in the BLL? 
*/ 
select ShortCode,Keyword,count([ClubID]) as ClubCount from 
(
    select p.ClubID,p.ShortCode,p.Keyword,p.ID 
    from dbo.Products p 
union all 
    select p.ClubID,p.ShortCode,PAK.Keyword,PAK.ID * -1 
    from dbo.ProductAdditionalKeywords as PAK 
    inner join dbo.Products P on PAK.ProductID = P.ID 
) as FullList 
group by Shortcode,Keyword 
order by Shortcode,Keyword 
+1

「產品」表中的關鍵字有什麼特殊之處,與「ProductAdditionalShortCodes」表中的(似乎命名錯誤的)表中的不同? – 2011-05-05 12:49:41

+0

@damien:這是「主要」關鍵字。額外的/其他的是人們使用和期望工作的錯誤拼寫。感謝錯誤命名的地方。我已糾正它。 :) – 2011-05-05 14:04:08

回答

2

我通常會這樣做,將所有的關鍵字放在一個單獨的表(例如什麼是當前您的附加表)。如果所有關鍵字在ShortCode中必須是不同的,那麼我也會在此表中包含ShortCode,以便可以在兩個列中應用唯一約束。

如果產品的所有關鍵字都必須在同一個ShortCode中,那麼我還會在產品中保留ShortCode。我會在該表中爲(ID,ShortCode)應用一個唯一約束,並在關鍵字表中引用一個額外的外鍵,引用兩邊的兩列。

我們留下什麼跟現在不包括在原來的設計中有兩個潛在的問題,但我不知道他們是否在實踐中關注的問題:

1)是關鍵字的產品更重要,還是特殊的,比額外的關鍵字?如果是這樣,我們需要在關鍵字表中添加一列來標記哪一個是重要的。爲確保只設置了一個,您可以搜索其他許多其他SO問題,這些問題涉及具有附加條件的唯一約束。 (讓我知道如果你找不到一個需要它,我肯定我可以添加一個鏈接,如果有必要)

2)應該允許一個產品沒有關鍵字?如果沒有,那麼我會創建一個模仿您的原始產品表的視圖。在這種情況下,如果1)以上是真實的,那麼我們總是加入「重要」關鍵字。否則,我們需要有一些方法將其限制爲每個產品的單行。我們拒絕在表上插入/更新/刪除,只允許他們通過視圖。3個相對簡單的觸發器將維護底層的表結構。

0

對你的設計,我不明白使用productAdditionalShortCodes沒有ShortCode字段。 但是,您可以使用ShortCode &關鍵字(組合鍵)添加唯一鍵約束。這將消除產品表中的重複條目。

+0

正如達米恩指出的那樣,這張表是錯誤的。我糾正了這一點。 – 2011-05-05 14:07:55

相關問題