2010-10-15 18 views
1

嘿,所以這裏有一個設計問題:日誌表中的外鍵

我正在處理一個項目,需要我跟蹤用戶何時執行插入,更新或刪除。我試圖決定的是,是否讓日誌表引用受影響的行的主鍵或其他標識符。爲了在使用外鍵時記錄刪除,我需要爲每個表都設置一個刪除列。但是,如果我使用某個沒有外鍵的命名標識符,我最終會在Logs表中運行名稱重複,並且它將變得不清楚該條目引用的內容。有沒有人有這方面的實際經驗,特別是使用刪除列以保持完整日誌的性能影響?

一個相關的問題也是在日誌表本身的設計中。如果我在單個日誌表中使用外鍵引用,那麼我的第一個直覺就是爲每個正在監視變化的表創建一個引用列。這對我來說並不理想,因爲如果我必須添加一個新表,我必須更改日誌表和任何關聯的sprocs。我可以看到的另一種選擇是有兩列,TableName和RowId。但是這將沒有固有的外鍵引用,因爲它不知道引用了什麼表。

感謝您的任何意見!

+1

刪除的標誌/列被稱爲邏輯刪除。使談話更輕鬆。 – 2010-10-15 19:42:01

回答

1

RE:一個日誌表,而不是影子表。

雖然這將會有更多的工作,但你不會從中得到太多的幫助。 - 加布裏埃爾麥克亞當斯

我不能不同意更多。

你的目標是:

保持當用戶執行插入,更新的軌跡,或刪除。

如果你對每個表影子表你怎麼回答這些問題:

  1. 哪些用戶昨天所做的更改?
  2. 什麼表有最新更新?
  3. 員工=「Page,S」上個月做了什麼活動?
  4. 什麼僱員是最活躍的?

你必須通過每個單獨的陰影表來弄清楚。如果你開始記錄一個新的表格,你必須記得改變這些sprocs來打這個新的影子表格。

如果您有其他人建議的日誌表,那麼您可以使用簡單的SQL輕鬆回答所有這些問題...... UNIT DELETE或UN-UPDATE最難做的是什麼。但是你並沒有爲此構建它,你正在構建它來跟蹤用戶的編輯,並且我列出的查詢或類似的查詢將成爲你的麪包和黃油。

關於邏輯刪除。

如果該表是您無法從其他表中刪除的父表,那麼它們可能很有用。像員工和工資單一樣。您不能刪除必須由法律保存的工資記錄的員工。如果這就是爲什麼你在邏輯上刪除,很好。但是,如果你在邏輯上刪除,以便你將PK保留在日誌表中的FK中,那麼我認爲你買了一個不太好的世界。

如果您有任何代碼直接觸及這些表格,您現在必須將它們全部更改爲包含DELETED ='F'謂詞。如果你從頭開始,你可以爲嵌入DELETED ='F'謂詞的每個邏輯刪除表創建一個視圖,並且從不授予對錶本身的選擇。

+0

我準備暫時設置單個日誌文件。正如你所提到的,對我來說,瞭解對你列出的問題的答案更重要。 – rpf3 2010-10-22 13:25:26

0

難道你不需要日誌表中的四列嗎? UserIdTableNameIdAction

Action將被「刪除」,「更新」或「插入」,Id將成爲有問題的表的主鍵,其餘的,自我解釋。

這樣你不必擁有大量的列和外鍵,這隻會使插入到日誌表中的速度變慢。無論如何,您需要使用觸發器來完成此操作,因此將表名添加到日誌表中不會成爲問題。

+1

-1 - 這不會顯示更新的列,並且您將丟失任何刪除信息 – 2010-10-15 16:46:02

+1

@Gabriel McAdams,我沒有注意到這是一項要求。 – 2010-10-15 16:48:09

0

假設您正在跟蹤的每個表的日誌信息都是相同的,我將使用帶有TableID和RowPKValue列的單個日誌表。的確,您無法將RowPKValue FK返回到每個單獨的表,但由於日誌表永遠不會被用戶(或LogS以外的任何代碼)觸及,所以我認爲這是相當安全的。

我肯定會使用行記錄的PK值而不是任何其他值(即使您沒有FK引用它),因爲這是PK值的用途。

至於DELETE問題,我認爲這取決於1)您希望執行的DELETE的數量,以及2)您將不得不將特徵「Undelete」作爲應用程序的一部分進行特徵化的可能性。

如果您的DELETE數量相對較少,您可以將它們保留在表格中並帶有已刪除的標記,然後在某個指定期限結束時將其刪除。如果你這樣做,我推薦一個基本表被稱爲CustomerAll的方案,並且前臺程序員可以使用單個表視圖CREATE VIEW Customer AS SELECT * FROM CustomerAll WHERE Deleted = false

如果你有大量的DELETE,我會將它們在DELETE時移動到第二個表(CustomersDeleted)或甚至在數據庫外,這取決於你認爲它有多可能需要查看它們再次。

1

首先,根據行數和您擁有的索引類型,添加刪除的列可能會更好,然後刪除該行。第二,我認爲最好的選擇是將整個行存儲在日誌表中(這也允許記錄任何更新)。你也可以用更規範化的記錄表做到這一點 - 是這樣的:

  • ID
  • 行動
  • EffectedColumn
  • 的OldValue
  • 的NewValue

這將是一個很大更多的工作,但是,你不會從中得到很多。我建議你將所有數據存儲在一張重複的表格中 - 用附加的列顯示所採取的行動。

至於對行標識符或其他值的引用,將會有相同的問題,但是你做到了。爲了確定哪一行受到影響,同一行中必須存在相同的唯一值。只要該行被刪除,那麼該唯一值(GUID(t-sql中的uniqueidentifier) - 順便說一句就是一個選項)。

+0

+1 - 特別針對重複的表格建議。雖然它可能會增加桌子,但我認爲它根本不是一個不好的選擇! – InSane 2010-10-15 16:55:35

0

也可以使用2表日誌文件設置。

洛加 - LOG_ID,表名,動作,DATE_TIME

LogB - LOG_ID,table_id的,columnchanged,OLD_VALUE,NEW_VALUE

(編輯calrify, 'table_id的' 上面是指無論是在你的主鍵多個PK可能需要多個字段)

在new_value字段中使用空值來表示舊值中的刪除和空值以表示插入。

如果您希望避免每個表上的「已刪除」列,您可以創建一個已刪除的表來存儲哪些行被刪除,並且使用一個視圖來僅顯示活動記錄(沒有自己的unqiue的IE記錄刪除表內的鍵)。

將會有很多的這種設計有效的辦法......