Иностранные ключи в журнале - PullRequest
1 голос
/ 15 октября 2010

Привет, вот вопрос дизайна:

Я работаю над проектом, который требует, чтобы я отслеживал, когда пользователь выполняет вставку, обновление или удаление. Я пытаюсь решить, будет ли таблица «Журналы» ссылаться на первичный ключ затронутой строки или какой-либо другой идентификатор. Чтобы регистрировать удаление при использовании внешних ключей, мне нужно иметь столбец «Удаленные» для каждой таблицы. Однако, если бы я использовал какой-то именованный идентификатор без внешнего ключа, я в итоге столкнулся бы с дублированием имени в таблице журналов, и стало бы неясно, к чему относится данная запись. Кто-нибудь имеет практический опыт с этим, особенно влияние на производительность использования столбца «Удаленные» для поддержки полных журналов?

Аналогичный вопрос также связан с дизайном самой таблицы журналов. Если я использую ссылки на внешние ключи в одной таблице журнала, мой первый инстинкт - создать столбец ссылок для каждой таблицы, которая отслеживается на предмет изменений. Это не кажется мне идеальным, как если бы мне нужно было добавить новую таблицу вниз по строке, а затем изменить таблицу журналов и любые связанные с ней спроки. Одна альтернатива, которую я вижу, состоит в том, чтобы иметь два столбца, TableName и RowId. Но это не будет иметь внутренних ссылок внешнего ключа, так как неизвестно, к какой таблице идет ссылка.

Спасибо за любой вклад!

Ответы [ 5 ]

2 голосов
/ 15 октября 2010

Во-первых, в зависимости от количества строк и того, какие у вас есть индексы, добавление удаленного столбца может работать лучше, чем удаление строки.

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

  • ID
  • Действие
  • EffectedColumn
  • OldValue
  • NewValue

Это было бы намного больше работы, хотя, и вы не получите столько от этого. Я бы порекомендовал вам просто хранить все данные в дублирующей таблице - с дополнительными столбцами, чтобы показать, какое действие было предпринято.

Что касается ссылки на идентификатор строки или какое-либо другое значение, возникла бы такая же проблема, как бы вы это ни делали. Чтобы определить, какая строка была произведена, в этой строке также должно существовать одно и то же уникальное значение. Как только эта строка будет удалена, это уникальное значение (кстати, GUID (uniqueidentifier в t-sql) - это опция).

1 голос
/ 15 октября 2010

RE: одна таблица журнала вместо теневых таблиц.

Это было бы намного больше работы, хотя, и вы не получили бы столько пользы от этого.- Габриэль МакАдамс

Я не мог не согласиться больше.

Ваша цель:

, чтобы отслеживать, когда пользователь выполняет вставку,Обновите или удалите.

Если у вас есть теневая таблица для каждой таблицы, как вы отвечаете на эти вопросы:

  1. Кто из пользователей внес изменения вчера?
  2. В какой таблице больше всего обновлений?
  3. Какую деятельность сотрудник = "Page, S" делал в прошлом месяце?
  4. Какой сотрудник наиболее активен?

Вам придется пройти через каждую отдельную теневую таблицу, чтобы понять это.И если вы когда-нибудь начнете регистрировать новую таблицу, вы должны будете помнить, что эти спроки также должны попадать в эту новую теневую таблицу.

Если у вас есть одна таблица журнала, как предлагали другие, вы можете ответить на все вопросы.эти вопросы очень легко с простым SQL ... что немного труднее сделать, UN-DELETE или UN-UPDATE.Но вы создаете его не для этого, вы создаете его для отслеживания правок пользователей, и запросы, которые я перечислил, или подобные им, будут вашими проблемами.

Относительно логических удалений.

Они могут быть полезны, если эта таблица является родителем других таблиц, из которых вы НЕ МОЖЕТЕ удалить.Понравился сотрудник и фонд заработной платы.Вы не можете удалить сотрудника с записями заработной платы, которые должны храниться по закону.Если именно поэтому вы логически удаляете, отлично.Но если вы логически удаляете, так что вы сохраняете PK в FK в журнальной таблице, то я думаю, что вы покупаете мир вреда за не очень большую пользу.

Если у вас есть ЛЮБОЙ код, попадающий в тенепосредственно для таблиц, теперь вам нужно изменить их ВСЕ, чтобы включить предикат DELETED = 'F'.Если вы начинаете с нуля, вы можете создать представление для КАЖДОЙ логически удаленной таблицы, которая содержит предикат DELETED = 'F' и никогда не предоставляет выбор для самой таблицы.

0 голосов
/ 15 октября 2010

Вы также можете использовать настройку файла журнала из 2 таблиц.

LogA - Log_id, имя таблицы, действие, date_time

LogB - Log_ID, идентификатор_таблицы столбца, old_value, новое_значение

(изменить до calrify, 'table_id' выше относится к любому первичному ключу в этой таблице. Для нескольких PK здесь может потребоваться более одного поля)

Использовать нулевое значение в поле new_value для представленияdelete и нулевое значение в старом значении для представления вставки.

Если вы предпочитаете избегать «удаленного» столбца в каждой таблице, вы можете создать удаленную таблицу, в которой хранятся строки, которые были удалены, и десять используют представление.показывать только активные записи (записи IE, у которых внутри удаленной таблицы нет своего ключа unqiue).

Будет много способов создания этого ...

0 голосов
/ 15 октября 2010

Предполагая, что информация журнала для каждой отслеживаемой таблицы идентична, я бы использовал одну таблицу журнала со столбцами TableID и RowPKValue.Это правда, что вы не можете FK, что RowPKValue вернуться к каждой отдельной таблице, но так как таблица журнала никогда не будет затронута пользователями (или любым кодом, кроме вашего Log SP), я думаю, что это достаточно безопасно.

Я бы определенноиспользуйте значение PK для регистрируемой строки, а не любое другое значение (даже если у вас нет FK, ссылающегося на него), потому что это то, для чего предназначены значения PK.

Что касается проблемы DELETE, ядумаю, что это зависит от 1) числа DELETE, которые вы ожидаете выполнить, и 2) вероятности того, что вам придется включить «Undelete» как часть приложения.

Если у вас относительно небольшое количество УДАЛЕНИЙ, вы можете сохранить их в таблице с удаленным флагом, а затем удалить их, когда истечет определенный период.Если вы сделаете это, я рекомендую схему, в которой базовая таблица называется как-то как CustomerAll, и у вас есть одно представление таблицы CREATE VIEW Customer AS SELECT * FROM CustomerAll WHERE Deleted = false для использования программистами переднего плана.

Если у вас большое количествоУДАЛИТЬ, я бы переместил их после УДАЛЕНИЯ во вторую таблицу (CustomersDeleted) или даже из базы данных, в зависимости от того, насколько вероятно, что вам когда-нибудь понадобится снова их искать.

0 голосов
/ 15 октября 2010

Разве вам не нужны четыре столбца в таблице журнала? UserId, TableName, Id, Action.

Action будет "удалять", "обновлять" или "вставлять", Id будет первичным ключом рассматриваемой таблицы, а остальные, ну, само собой разумеется.

Таким образом, вам не нужно иметь много столбцов и внешних ключей, что только замедлит вставку в таблицу Log. В любом случае вам придется делать это с триггерами, поэтому добавление имени таблицы в таблицу журнала не составит проблемы.

...