Можете да добавите стойността на id в края на името, когато се изтрие запис, така че когато някой изтрие id 3, името става Thingy3_3 и след това, когато изтрие id 100, името става Thingy3_100. Това ще ви позволи да създадете уникален съставен индекс на името и изтритите полета, но след това трябва да филтрирате колоната с име всеки път, когато я показвате и да премахнете идентификатора от края на името.
Може би по-добро решение би било да замените вашата изтрита колона с deleted_at колона от тип DATETIME. След това можете да поддържате уникален индекс на name и deleted at, като неизтрит запис има нулева стойност в полето deleted_at. Това ще предотврати създаването на множество имена в активно състояние, но ще ви позволи да изтриете едно и също име няколко пъти.
Очевидно трябва да направите тест, когато възстановявате изтриване на запис, за да се уверите, че няма ред със същото име и нулево поле deleted_at, преди да разрешите премахването на изтриването.
Всъщност можете да приложите цялата тази логика в базата данни, като използвате тригер INSTEAD-OF за изтриването. Този тригер няма да изтрие записи, а вместо това ще актуализира колоната deleted_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
Така че във вашия код можете да изтривате записи, като използвате нормално изтриване и оставяте тригера да се погрижи за подробностите. Единственият възможен проблем (който можех да видя) беше, че изтриването на вече изтрити записи може да доведе до дублиращи се редове, следователно условието в тригера да не се актуализира полето deleted_at на вече изтрит ред.