Помните, что Google Play занимает некоторое время, чтобы опубликовать новую версию в магазине Play. Потому что он проверяет каждый раз, когда вы загружаете новый APK. Предыдущий APk будет сохранен после запуска нового apk.
Вы можете добавить значение id в конец имени, когда запись удаляется, поэтому, когда кто-то удаляет идентификатор 3, имя становится Thingy3_3, а затем, когда он удаляет идентификатор 100, имя становится Thingy3_100. Это позволило бы вам создать уникальный составной индекс по имени и удаленным полям, но затем вам придется фильтровать столбец имени при каждом его отображении и удалять идентификатор из конца имени.
Возможно, лучшим решением будет замените свой удаленный столбец на столбец delete_at типа DATETIME. Затем можно сохранить уникальный индекс по имени и удаленному адресу, а не удаленная запись будет иметь нулевое значение в поле delete_at. Это предотвратит создание нескольких имен в активном состоянии, но позволит вам удалить одно и то же имя несколько раз.
Очевидно, что вам нужно выполнить тест при удалении записи, чтобы убедиться, что нет строки с тем же именем и пустое поле selected_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
. Таким образом, в вашем коде вы можете удалять записи. используя обычное удаление, и пусть триггер позаботится о деталях.
Для простой таблицы с именем [Test] с идентификаторами столбцов (int), Filter (nvarchar), Deleted ( бит)
ALTER TABLE [dbo].[Test] ADD
CONSTRAINT [DF_Test_Deleted] DEFAULT (0) FOR [Deleted],
CONSTRAINT [IX_Test] UNIQUE NONCLUSTERED
(
[filter],
[Deleted]
) ON [PRIMARY]
Возможно, стоит подумать об использовании таблицы «Корзина». Вместо того чтобы хранить старые записи в той же таблице с флагом, переместите их в свою собственную таблицу со своими собственными ограничениями. Например, в активной таблице у вас есть ограничение UNIQUE на имя, а в таблице корзины - нет.
Проблема с составным уникальным ограничением состоит в том, что невозможно удалить несколько записей с одинаковым именем. Это означает, что система сломается, как только вы удалите третью запись. Я бы не рекомендовал добавлять материал к именам, потому что теоретически может возникнуть дублирующая ситуация. Кроме того, тем самым вы в основном повреждаете данные в базе данных, а также добавляете загадочную бизнес-логику к самим данным.
Единственное возможное решение для всей базы данных - это добавить триггер, который проверяет, что вставленный / обновленный данные действительны. Также возможно поместить проверки вне базы данных в код.
Например, вы можете добавить недопустимый символ (*) к удаленному имени. Но у вас все еще есть проблемы с удалением удаленного элемента. Поэтому, вероятно, лучшая идея - запретить двойные имена, даже если они удалены.
Вы можете очистить удаленные записи через некоторое время (или переместить их в отдельную таблицу).
Добавить случайный хеш после уникального имени. То, что легко обратимо. Возможно разделение подчеркиванием или другим символом.
Редактировать после комментария: Вы можете просто добавить подчеркивание и текущую метку времени.
Не конечно же, в SQLServer2005, но вы можете определить составные ограничения / индексы
CREATE UNIQUE INDEX [MyINDEX] ON [TABLENAME] ([NAME] , [DELETED])
Как указал SteveWeet, это позволит вам только удалить / создать дважды.
Тип ограничения, который вам нужен - это ограничение CHECK
на уровне таблицы, т.е. ограничение CHECK, состоящее из подзапроса, который проверяет NOT EXISTS
(или эквивалент) для таблицы, например,
CREATE TABLE Test
(
ID INTEGER NOT NULL UNIQUE,
name VARCHAR(30) NOT NULL,
deleted INTEGER NOT NULL,
CHECK (deleted IN (0, 1))
);
ALTER TABLE Test ADD
CONSTRAINT test1__unique_non_deleted
CHECK
(
NOT EXISTS
(
SELECT T1.name
FROM Test AS T1
WHERE T1.deleted = 0
GROUP
BY T1.Name
HAVING COUNT(*) > 1
)
);
INSERT INTO Test (ID, name, deleted) VALUES (1, 'Thingy1', 0)
;
INSERT INTO Test (ID, name, deleted) VALUES (2, 'Thingy2', 0)
;
INSERT INTO Test (ID, name, deleted) VALUES (3, 'Thingy3', 1)
;
INSERT INTO Test (ID, name, deleted) VALUES (4, 'Thingy3', 1)
;
INSERT INTO Test (ID, name, deleted) VALUES (5, 'Thingy3', 0)
;
INSERT INTO Test (ID, name, deleted) VALUES (6, 'Thingy3', 0)
;
Последний INSERT
(ID = 6) заставит ограничение сработать и INSERT
будет провален. Q.E.D.
... ох, чуть не забыл упомянуть: SQL Server пока не поддерживает CHECK
ограничения, содержащие подзапрос (я тестировал вышеописанное на ACE/JET, a.k.a. ). Хотя вы могли бы использовать ФУНКЦИЮ
, я читал, что это небезопасно из-за того, что SQL Server тестирует ограничения по строкам (см. блог Дэвида Портаса). Пока эта функция SQL-92 не будет полностью поддерживаться в SQL Server, я предпочитаю использовать ту же логику в триггере.
Создать уникальное ограничение для (имя удалено). Однако это будет означать, что вы можете удалить только одно имя.
Очевидный обходной путь для , который работает под ANSI-92, но не на MS SQLServer: https: // connect. microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=299229
Вместо удаленного столбца используйте столбец end_date. Когда пользователь удаляет запись, добавьте текущую дату в столбец end_date. Любые записи, в которых столбец end_date равен NULL, являются вашими текущими записями. Определите уникальное ограничение для двух столбцов name и end_date. Из-за этого ограничения у вас никогда не будет сценария, в котором правильное имя записи будет продублировано. Каждый раз, когда пользователь хочет восстановить запись, вам нужно установить для столбца end_date значение null, и если это нарушает ограничение уникальности, вы показываете пользователю сообщения, что такое имя уже существует.