2011-05-05 60 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

相关问题