2010-10-22 4 views
5

У меня есть таблица, что-то вродеограничение уникальности управляется битовой колонке

FieldsOnForms(
FieldID int (FK_Fields) 
FormID int (FK_Forms) 
isDeleted bit 
) 

пара (FieldID, FormID) должен быть уникальным, но только если строка не удаляется (IsDeleted = 0).

Можно ли определить такое ограничение в SQLServer 2008? (без использования триггеров)

P.S. Параметр Setting (FieldID, FormID, isDeleted) уникален, добавляет возможность отмечать одну строку как удаленную, но я хотел бы иметь возможность установить n строк (для каждого идентификатора FieldID, FormID) на isDeleted = 1 и иметь только один с IsDeleted = 0

ответ

12

вы можете иметь уникальный индекс, используя 2008 filtered indexes функции Сервера SQL, или вы можете применить уникальный индекс на вид (фильтрованное индекс бедняка, работает против более ранних версий), но вы не можете иметь УНИКАЛЬНОЕ ограничение, как вы описали.

Пример отфильтрованного индекса:

CREATE UNIQUE NONCLUSTERED INDEX IX_FieldsOnForms_NonDeletedUnique ON FieldsOnForms (FieldID,FormID) WHERE isDeleted=0 
+0

+1 лучший ответ ... – gbn

+0

Хотя у меня есть некоторая ошибка из-за поля бит (преобразование столбца в тип данных константы не поддерживается для фильтрованных индексов), это, по-видимому, решение, к которому я уже обращался. – jaraics

+0

@jaraics - Я только что создал таблицу в вашем вопросе, а затем индекс в своем ответе, и он создан без ошибок. Кроме того, если вы сталкиваетесь с несоответствиями типа данных, обычно лучше использовать CAST (или CONVERT) константу для типа столбца, а не наоборот. Не уверен, что это исправит вашу проблему. –

1

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

2

Вы можете изменить столбец IsDeleted на DeletedDate и сделать его DATETIME с точным временем, когда строка была логически удалена. Кроме того, вы можете добавить столбец DeletedDate, а затем создать расчётный столбец IsDeleted, чтобы он оставался доступным для этого столбца, если он используется в коде. Вы, конечно, поместили бы уникальный индекс поверх DeletedDate (помимо FieldID и FormId) вместо столбца IsDeleted. Это позволило бы точно указать один столбец NULL.

Albin опубликовал решение, подобное этому, но затем удалил его. Я не знаю, почему, но если он снова запишет его, то он был здесь до моего. :)

+0

Это, кажется, хороший альтернативный вариант для более ранних SQL-серверов. – jaraics

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