我繼承了SQL Server 2008數據庫,調用應用程序可以通過存儲過程訪問該數據庫。是否可以確定是否從存儲過程發出DML命令?
數據庫中的每個表都有一個影子審計表,其中記錄了插入/更新/刪除操作。
對填充審計表進行性能測試表明,使用OUTPUT
子句插入審計記錄的速度比使用觸發器快20%,所以這已在存儲過程中實現。但是,由於此設計無法跟蹤通過直接對錶發出的DML語句直接對錶進行的更改,因此還使用觸發器來使用值@@NESTLEVEL
來確定是否運行觸發器(假設爲所有通過存儲過程運行的DML將具有@@NESTLEVEL
> 1)。 即觸發代碼的機身看起來是這樣的:
IF @@NESTLEVEL = 1 -- implies call is direct sql so generate history from here
BEGIN
... insert into audit table
這種設計是有缺陷的,因爲它不會追蹤DML語句在動態SQL執行更新,或者@@NESTLEVEL
以上1提出的任何其他方面。
任何人都可以提出一個完全可靠的方法,我們可以在觸發器中使用,只有在沒有觸發存儲過程時才能執行它們嗎?
或者這是(我懷疑)不可能?
明智的做法是防守編程,並將您的代幣「添加」到CONTEXT_INFO中已經設置的任何代碼中?同樣,因爲它是基於連接的,不應該在程序結束時清除它們的標記嗎?如果一個proc調用一個proc,你應該只添加/清除它是否已經存在?可能會變得棘手,但仍然,這聽起來非常可靠。 – 2010-05-14 13:59:17
@Philip Kelley,在上面的簡單示例中,我通過執行'SET CONTEXT_INFO 0x0'來清除它,您可以在更改它之前存儲它的值,然後將其設置回來。你也可以推/推動價值等等。可能性只是無盡的,這只是一個簡單的例子,而不是一個完整的機制。 – 2010-05-14 14:05:47
謝謝 - 這是一個很好的解決方案。 – 2010-05-15 08:55:29