2015-07-13 1 views
2

Это мой стол:Создать уникальное ограничение изначально отключена

CREATE TABLE [dbo].[TestTable] 
(
    [Name1] varchar(50) COLLATE French_CI_AS NOT NULL, 
    [Name2] varchar(255) COLLATE French_CI_AS NULL, 
    CONSTRAINT [TestTable_uniqueName1] UNIQUE ([Name1]), 
    CONSTRAINT [TestTable_uniqueName1Name2] UNIQUE ([Name1], [Name2]) 
) 

ALTER TABLE [dbo].[TestTable] 
ADD CONSTRAINT [TestTable_uniqueName1] 
UNIQUE NONCLUSTERED ([Name1]) 

ALTER TABLE [dbo].[TestTable] 
ADD CONSTRAINT [TestTable_uniqueName1Name2] 
UNIQUE NONCLUSTERED ([Name1], [Name2]) 
GO 

ALTER INDEX [TestTable_uniqueName1] 
    ON [dbo].[TestTable] 
    DISABLE 
GO 

Моя идея заключается в том, чтобы включить/выключить один или другой уникальный contraint в зависимости от клиента приложения. Таким образом, я могу поймать заброшенное исключение в моем коде C# и отобразить конкретное сообщение об ошибке в GUI.

Теперь моя проблема заключается в изменении параметров сортировки столбцов Name1 & Name2, мне нужно, чтобы сделать их случай чувствительный (French_CS_AS). Чтобы изменить эти поля, мне нужно отбросить два ограничения и воссоздать их. Согласно объясненной схеме, я не могу создать включенное ограничение, а затем отключить его, потому что некоторые клиенты имеют дубликаты ключей для одного или другого ограничения.

Для моего сценария обновления, моя идея номер 1 был

  1. Сохранить имя разрешенных ограничений в таблице темпа
  2. падения ограничений
  3. Alter колонны
  4. Создание ИНВАЛИДЫ уникальных ограничений
  5. Включить определенные ограничения в соответствии с сохраненными значениями в точках 1.

Моя проблема в пункте 4. Я не могу найти, как создать отключенное уникальное ограничение с помощью инструкции ALTER TABLE. Можно ли создать его непосредственно в таблице sys.indexes?

Моя идея номер 2 был

  1. Rename TestTable в TestTableCopy
  2. Recreate TESTTABLE с новыми полями сортировки, а в противном случае та же схемы (индексы, FK, триггеры, ...)
  3. Отключить specifical уникальных контрсилами в TestTable
  4. Перенос данных из TestTableCopy в TESTTABLE
  5. падения TestTableCopy

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

Есть ли другой способ достижения моей цели?

При необходимости я могу использовать уникальные индексы вместо уникальных ограничений.

+0

Почему вы не можете забыть об ограничении Unique и проверить себя и поймать исключение при добавлении записи в таблицу? – CiucaS

+0

Поскольку записи можно вставлять разными способами (с t-sql, из моего приложения C#, ...). Я хочу, чтобы база данных проверяла мои данные. – stephanejulien

+0

создайте хранимую процедуру для вставки записей в таблицу, вы можете использовать ее для всех типов вставок, которые вам нужны. В хранимой процедуре проверьте ограничение, основанное на том, что вам нужно. Так бы я сделал это. Изменение таблицы не является хорошей практикой. – CiucaS

ответ

1

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

Таким образом, вместо того, чтобы иметь инвалида уникальный индекс либо:

  • нет индекса вообще (который является таким же, как имеющие инвалида индекс с точки процессора запроса зрения),
  • или создать не уникальный индекс.

Для тех объектов, где ваш клиент имеет уникальные данные, создайте уникальный индекс. Для тех объектов, где ваш клиент имеет уникальные данные, создается неидеальный индекс.

+0

Вы правы! Я искал по-разному, невозможно создать отключенное уникальное ограничение или отключенный уникальный индекс. Мое решение - отказаться от моих ограничений, изменить мои столбцы и воссоздать только тех, кто изначально был включен. – stephanejulien

0
CREATE PROCEDURE [dbo].[spUsers_AddUsers] 
@Name1 varchar(50) , 
@Name2 varchar(50) , 
@Unique bit 
AS 

declare @err int 
begin tran 
    if @Unique = 1 begin 
if not exists (SELECT * FROM Users WHERE Name1 = @Name1 and Name2 = @Name2) 
begin 
    INSERT INTO Users (Name1,Name2) 
    VALUES (@Name1,@Name2) 
    set @err = @@ERROR 
end else 
begin 
    UPDATE Users 
    set Name1 = @Name1, 
    Name2 = @Name2 
    where Name1 = @Name1 and Name2 = @Name2 
    set @err = @@ERROR 
end 

end else begin 
    if not exists (SELECT * FROM Users WHERE Name1 = @Name1) 
    begin 
     INSERT INTO Users (Name1,Name2) 
     VALUES (@Name1,@Name2) 
     set @err = @@ERROR 
    end else 
    begin 
    UPDATE Users 
    set Name1 = @Name1, 
     Name2 = @Name2 
    where Name1 = @Name1 
    set @err = @@ERROR 
end 


if @err = 0 commit tran 
    else rollback tran 

Итак, сначала вы проверяете наличие уникального Name1 и Name2 или просто Name1. Затем, если вы сделаете вставку/обновление, основанное на том, что у вас есть.

+0

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

+0

Это не так, я использую ограничения все время, и они являются очень важной частью в каждом дБ, но ваша ситуация кажется немного страшной, и я никогда не сталкивался с ней (необходимость менять ограничение каждый раз). – CiucaS