Вы можете добавить значение id в конец имени, когда запись удаляется, поэтому, когда кто-то удаляет идентификатор 3, имя становится Thingy3_3, а затем, когда они удаляют идентификатор 100, имя становится Thingy3_100. Это позволит вам создать уникальный составной индекс для имени и удаленных полей, но вам придется фильтровать столбец имени при каждом его отображении и удалять идентификатор в конце имени.
Возможно, лучшим решением было бы заменить удаленный столбец на столбец delete_at типа DATETIME. Затем вы можете сохранить уникальный индекс для имени и удаленного в, с не удаленной записью, имеющей нулевое значение в поле delete_at. Это предотвратит создание нескольких имен в активном состоянии, но позволит удалить одно и то же имя несколько раз.
Очевидно, что вам нужно выполнить тест при восстановлении записи, чтобы убедиться, что нет строки с тем же именем и пустым полем delete_at, прежде чем разрешить удаление.
Вы могли бы фактически реализовать всю эту логику в базе данных, используя триггер INSTEAD-OF для удаления. Этот триггер не удаляет записи, а обновляет столбец delete_at при удалении записи.
Следующий пример кода демонстрирует это
CREATE TABLE swtest (
id INT IDENTITY,
name NVARCHAR(20),
deleted_at DATETIME
)
GO
CREATE TRIGGER tr_swtest_delete ON swtest
INSTEAD OF DELETE
AS
BEGIN
UPDATE swtest SET deleted_at = getDate()
WHERE id IN (SELECT deleted.id FROM deleted)
AND deleted_at IS NULL -- Required to prevent duplicates when deleting already deleted records
END
GO
CREATE UNIQUE INDEX ix_swtest1 ON swtest(name, deleted_at)
INSERT INTO swtest (name) VALUES ('Thingy1')
INSERT INTO swtest (name) VALUES ('Thingy2')
DELETE FROM swtest WHERE id = SCOPE_IDENTITY()
INSERT INTO swtest (name) VALUES ('Thingy2')
DELETE FROM swtest WHERE id = SCOPE_IDENTITY()
INSERT INTO swtest (name) VALUES ('Thingy2')
SELECT * FROM swtest
DROP TABLE swtest
Выбор из этого запроса возвращает следующее
id name deleted_at
1 Thingy1 NULL
2 Thingy2 2009-04-21 08:55:38.180
3 Thingy2 2009-04-21 08:55:38.307
4 Thingy2 NULL
Таким образом, в вашем коде вы можете удалять записи, используя обычное удаление, и позволить триггеру позаботиться о деталях. Единственная возможная проблема (которую я мог видеть) заключалась в том, что удаление уже удаленных записей может привести к дублированию строк, поэтому в триггере возникает условие не обновлять поле delete_at в уже удаленной строке.