Вопрос разработки схемы SQL - удалите флаги - PullRequest
3 голосов
/ 12 февраля 2010

в нашей схеме базы данных нам нравится использовать флаги удаления. Когда запись удаляется, мы обновляем это поле, а не выполняем оператор удаления. Затем остальные наши запросы проверяют наличие флага удаления при возврате данных.

Вот проблема:

Флаг удаления - это дата со значением по умолчанию NULL. Это удобно, потому что когда запись удалена, мы можем легко увидеть дату, когда она была удалена.

Однако, чтобы правильно применить уникальные ограничения, нам нужно включить флаг удаления в уникальное ограничение. Проблема в том, что в MS SQL он ведет себя в соответствии с тем, что мы хотим (для этой схемы), но в postgresql, если какое-либо поле в многостолбцовом уникальном ограничении равно NULL, оно разрешает это поле. Такое поведение соответствует стандарту SQL, но нарушает наш дизайн.

Варианты, которые мы рассматриваем:

  1. установить значение по умолчанию для удаленного поля в качестве некоторой жестко закодированной даты

  2. добавить битовый флаг для удаленного, тогда каждая таблица будет иметь 2 связанных поля удаления - date_deleted и is_deleted (например)

  3. изменить дату_установлено на is_deleted (битовое поле)

Я подозреваю, что вариант 1 - это снижение производительности, каждый запрос должен проверять жестко заданную дату, а не просто проверять IsNUll. Плюс это неправильно.

Вариант 2 также кажется неправильным - 2 поля для «удаленных» не являются сухими.

Вариант 3, мы теряем информацию о «дате». Существует измененное поле, которое теоретически будет отражать дату удаления, но только при условии, что последнее обновление строки было обновлением бита удаления.

Итак, есть предложения? Что вы сделали в прошлом, чтобы справиться с «удалением флагов»?

Обновление Спасибо всем за супер быстрые и вдумчивые ответы. Мы закончили с простым логическим полем и измененным полем даты (с триггером). Я только что заметил предложение частичного индекса, и это выглядит как идеальное решение для этой проблемы (но я на самом деле не пробовал)

Ответы [ 7 ]

4 голосов
/ 12 февраля 2010

Если для вас важно просто сохранить удаленные записи, рассматривали ли вы просто перемещение их в таблицу истории?

  • Этого легко добиться с помощью триггера.
  • Логика приложения не должна учитывать этот удаленный флаг.
  • Ваши таблицы останутся худыми и будут означать при выборе из них.
  • Это решит вашу проблему с уникальными индексами.
3 голосов
/ 12 февраля 2010

Просто создайте условное уникальное ограничение:

CREATE UNIQUE INDEX i_bla ON yourtable (colname) WHERE date_deleted IS NULL;
3 голосов
/ 12 февраля 2010

А как насчет триггеров? Когда запись удаляется, триггер пост-обновления копирует строку в архивную таблицу, которая имеет такую ​​же структуру, плюс любые дополнительные столбцы и дополнительный столбец даты / времени и, возможно, пользователя, который удалил ее.

Таким образом, ваша «живая» таблица содержит только те записи, которые фактически являются живыми, поэтому это лучше с точки зрения производительности, и вашему приложению не нужно беспокоиться о том, была ли удалена запись.

3 голосов
/ 12 февраля 2010

Вариант 3, мы теряем «дату» Информация. Есть модифицированный поле, которое теоретически отражало бы дата удалена, но только при условии последнее обновление строки было обновить до бита удаления.

Есть ли коммерческая причина, по которой запись будет изменена после ее удаления? Если нет, беспокоитесь ли вы о чем-то, что на самом деле не является проблемой? =)

В системе, над которой я сейчас работаю, у нас есть следующие столбцы метаданных: _Deleted, _CreatedStamp, _UpdatedStamp, _UpdatedUserId, _CreatedUserId ... совсем немного, но для этой системы важно нести столько данных. Я бы посоветовал пойти по пути наличия отдельного флага для «Удалено до измененной даты / Дата удаления». «Дисковое пространство - это дешево», а наличие двух полей для представления удаленной записи не является окончанием мира, если это то, что вам нужно сделать для используемой СУБД.

2 голосов
/ 12 февраля 2010

Одно из моих любимых решений - битовый флаг is_deleted и поле даты last_modified.

Поле last_modified обновляется автоматически при каждом изменении строки (с использованием любого метода, поддерживаемого вашей СУБД.) Если битовый флаг is_deleted равен TRUE, то значение last_modified подразумевает время, когда строка была Исключен.

После этого вы сможете установить значение по умолчанию от last_modified до GETDATE(). Нет больше значений NULL, и это должно работать с вашими уникальными ограничениями.

0 голосов
/ 12 февраля 2010

Можно ли исключить удаленное поле даты из вашего уникального индекса? Каким образом это поле вносит вклад в уникальность каждой записи, особенно если поле обычно равно нулю?

0 голосов
/ 12 февраля 2010

Достигнет ли создание уникального индекса из нескольких столбцов, включающего в себя удаленную дату, того же предела ограничения, который вам нужен?дата удаления до минимальной даты sql = 0 или «1/1/1753» вместо значения NULL для неосуществленных записей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...