2010-10-15 3 views
1

Эй, так что немного дизайнерского вопрос здесь:внешних ключей в таблице журнала

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

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

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

+1

Удаленный флаг/столбец называется логическим удалением. Делает разговор проще. –

ответ

1

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

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

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

Ваша цель состоит в том, чтобы:

отслеживать, когда пользователь выполняет Insert, Update или Delete.

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

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

Вам нужно пройти КАЖДОЙ ОДИН Тени-стол, чтобы понять это. И если вы когда-нибудь начнете регистрировать новую таблицу, вам придется не забудьте изменить эти sprocs, чтобы также попасть в эту новую таблицу теней.

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

Что касается логических ошибок.

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

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

+0

Я пока собираюсь с единственным файлом журнала, установленным на данный момент. Как вы упомянули, мне важнее знать ответы на такие вопросы, как те, которые вы указали. – rpf3

0

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

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

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

+1

-1 - Это не покажет, какие столбцы были обновлены, и вы потеряете информацию о любых удалениях –

+1

@Gabriel McAdams, я не заметил, что это было требованием. –

0

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

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

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

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

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

1

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

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

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

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

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

+0

+1 - особенно для дублированного предложения таблицы. Хотя это может увеличить таблицы, я думаю, что это вовсе не плохой вариант рассмотреть! – InSane

0

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

Лога - Log_id, TABLENAME, действие, date_time

LogB - Log_ID, table_id, columnchanged, old_value, new_value

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

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

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

Там будет много действительных способов разработки этого ...

Смежные вопросы