2013-11-20 5 views
7

Учитывая следующую таблицу (и выборочные данные):SQL Server Условный Уникальный индекс

PK | ClientID | SetID | Title 
----------------------------- 
P1 | C1  | S1 | Title1 
P2 | C1  | S1 | Title1 
P3 | C2  | S2 | Title1 
P4 | C2  | S2 | Title1 
P3 | C1  | S3 | Title2 
P5 | C1  | S3 | Title2 

Предполагая Set принадлежит к Client, я могу иметь уникальный индекс, ограничения Заголовок, уникальным в пределах клиента за исключением это братья и сестры в одном наборе.

Так, например, я могу иметь Title1 в двух Clients, но не дважды в одном Client. Теперь для Client1, я хочу иметь вторую запись с Title1, но только когда она имеет тот же SetID, как и все остальные с Title.

Просто для того, чтобы отметить, я использую SQL Azure, но мне больше нравится (например, 2008 R2/2012).

Edit:
Пожалуйста, обратите внимание, что я не могу изменить структуру таблицы. Он существует уже таким образом и имеет за собой сложный бизнес-уровень. Если я могу исправить это, как есть, тогда здорово, если нет, то я могу оставить его сломанным.

+0

Я не могу видеть, как вы будете иметь уникальный индекс три столбца, которые позволяют дублировать информацию. Я полагаю, что это может быть исправлено, только если вы добавите, например, столбец идентификаторов, чтобы быть частью индекса, но вам не разрешено изменять таблицу. – gotqn

+0

Я могу добавить столбец, но не могу сделать навязчивые изменения, такие как разделение таблицы на две части. –

+0

@gotqn. Это не должен быть уникальный индекс, это то, что я думаю, будет делать трюк, просто не понял, как! :) –

ответ

2

Вы можете попробовать дополнительный индексный вид.

Например, таблица:

create table dbo.Test (PK int, ClientID int, SetID int, Title varchar(50), primary key (PK)) 

insert into dbo.Test values 
    (1, 1, 1, 'Title1') 
    ,(2, 1, 1, 'Title1') 
    ,(3, 2, 2, 'Title1') 
    ,(4, 2, 2, 'Title1') 
    ,(5, 1, 3, 'Title2') 
    ,(6, 1, 3, 'Title2') 

Вид и индекс:

create view dbo.vTest 
with schemabinding 
as 
    select ClientID, Title, SetID, cnt=count_big(*) 
    from dbo.Test 
    group by ClientID, Title, SetID 
GO 
create unique clustered index UX_vTest on dbo.vTest (ClientID, Title) 
GO 

Тогда:

insert into dbo.Test values (7, 1, 1, 'Title1') -- will pass 
insert into dbo.Test values (8, 1, 1, 'Title1') -- will pass 
insert into dbo.Test values (9, 1, 2, 'Title1') -- will fail 
insert into dbo.Test values (10, 2, 2, 'Title1') -- will pass 
insert into dbo.Test values (11, 1, 3, 'Title1') -- will fail 
+0

Это маршрут, который я больше всего рассматриваю. Спасибо за ваше время. –

0

Если бы я получил вопрос прямо, я хотел бы добавить еще одну таблицу, чтобы связать между SetID и Title, которые имеют 1:1 отношение и добавить уникальный индекс на ClientID and SetID

CREATE UNIQUE INDEX [Index_Name] 
ON [dbo].[MyTable]([ClientID ], [SetID]) 
+0

Спасибо за совет. Я согласен, что это будет лучше, но, к сожалению, у меня нет возможности изменить структуру. Мои параметры: добавить столбцы (вычисляемые?), Добавить индексы, представления и т. Д. –

0

как о добавлении на триггер вставки/обновления, выполняет проверки и вызывает исключение сбоя, если правило нарушено. вы можете добавить их без изменения модели данных.

+0

Я это рассмотрел, но он чувствует себя немного грязным. Я использую триггер AFTER INSERT DML для цели, которая действительно нужна ПЕРЕД НАСТРОЕНИЕМ. Моя проблема с использованием триггера для этого - производительность. Можете ли вы предоставить плюсы и минусы? –

+0

Если вы можете использовать триггер, вы можете создать триггер INSTEAD OF INSERT для обработки вставки и выполнить проверку. – gotqn

+0

@gotgn. Спасибо, я знаю об этом, но триггер INSTEAD OF требует, чтобы я переписал вставку, которая произошла бы.Я был бы доволен тем, что если бы я смог сделать «INSERT INTO [table] SELECT * FROM INSERTED», но я не могу это сделать с идентификаторами. –

Смежные вопросы