2013-02-05 53 views
6

我有一個120列的表。我需要設置審計跟蹤,如果更改了任何列,就會記錄它。因爲它是現在,我想我必須建立與條件是這樣的一個觸發每列:MySQL更新觸發器 - 找到更改的列?

IF(NEW.columnName != OLD.columnName) 
THEN //log the old value 

這將需要進行120次......雖然我已經接受了這種方式20年以前,今天我拒絕相信自動化這樣一個簡單的程序自動找到更改的列是不可能的。

這是我迄今發現:

  • 既不新鮮也不OLD是一個表,它是一種語言結構,因此,你可以不會做或類似的東西「現在選擇*。」
  • 動態SQL在觸發器中是不允許的(這可能解決了這個問題)。
  • 在觸發器中不允許使用動態SQL的過程(嚴重的是,Oracle,無論如何,看起來您都很努力禁用此功能)。

我正在考慮使用BEFORE和AFTER觸發器與臨時表和變量一起使用,這可能會解決問題,但是又需要動態SQL。我覺得我陷入了死衚衕。

有沒有解決方案呢?

一個問題:在PostgreSQL中可能嗎?

更新:我發現2個可能的解決方案。然而他們都不看不夠清楚對我說:使用活動作爲一種解決方法結合使用觸發器使用動態SQL workaround

  • 。我不得不承認,我不太明白,這是否意味着EVENT無論如何都會每秒發射一次?
  • This article表示只要使用臨時表就可以在觸發器內使用動態SQL。這仍然使用動態SQL,所以我不太明白。
+0

你檢查這與[在Postgres的會話信息函數爲您的最後一個問題](http://stackoverflow.com/questions/8759595/within-a-trigger-function-how-to-get-which-fields-are-being-updated ) – bonCodigo

+0

@bonCodigo謝謝,顯然PostgreSQL在這種情況下更加靈活。 – Caballero

回答

1

有趣的是,幾年前我面臨着同樣的問題,實現基於動態觸發器的審計日誌。我想出的解決方案是簡單地生成SQL觸發器代碼,然後可以(自動)應用它來替換舊的觸發器定義。如果內存服務,我創建了幾個SQL模板,這些模板由一個PHP腳本處理,而後者基於「SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE ...」輸出完整的觸發器定義。是的,觸發器代碼非常大,但它工作正常!希望有一點幫助=)

+2

感謝您的回答,但是我選擇使用觸發器的唯一原因是我不必涉及PHP - 如果我選擇使用PHP實現此功能,則不會存在此問題。我有一個龐大的系統已經在PHP編碼,如果我不得不在那裏執行代碼審計這將是自殺。 – Caballero

0

我通過創建一個影子表爲一個項目做了這個。如果你不處理數以百萬計的更新,當用戶登錄這可能工作

  • ,SET @user_id = {登錄的用戶ID}
  • 在表上創建一個觸發器之前更新複製的行將其修改爲具有相同結構的影子表(注意,影子表中不能包含主鍵,也不能具有唯一鍵)
  • 向影子表(modified_by,modified_on)添加其他列
  • 創建一個小型php腳本顯示列之間的差異 - 這種方式你不touvh現有的PHP代碼庫
  • 如果你正在處理大量的更新,並希望保持影子表小,一個cron可以寫入解析影子表,並確定哪些列發生變化,只是這個信息存儲到另一個表