У меня есть 3 таблицы в SQL Server 2008
- Клубы с удостоверением личности и именем.
- Продукты, которые имеют PK ID, FK ClubID, имя, шорткод и ключевое слово.
- Существует Великобритания, которая обязана обеспечить отсутствие дублирующих ключевых слов для комбинаций ShortCode / Keyword.
- ProductAdditionalShortCodes. У этого есть PK ID, FK ProductID и Ключевое слово
Идея состоит в том, чтобы запретить любую комбинацию шорткода / ключевого слова продуктов, указывающих на разные клубы, а также предотвратить создание дублированных комбинаций короткого кода / ключевого слова
У меня есть решение, которое работает, но кажется неуклюжим и может при определенных обстоятельствах потерпеть неудачу, если несколько пользователей одновременно обновили несколько записей. (Гипотетически)
Как я могу добавить какую-либо форму ограничения к БД, чтобы ключевое слово в основной таблице не совпадало с таблицей «Дополнительно» и наоборот?
Ниже приведен пример сценария для создания сценария и некоторые примеры, которые я хочу предотвратить. Я не против изменения структуры БД, если влияние этого изменения не нарушит слишком многих других аспектов решения. (Я понимаю, что это субъективно)
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