简体   繁体   中英

Feasibility of SQLCLR Trigger or Stored Procedure for Audit Trail?

Disclaimer: I am unable to implement this properly in the application, as the application I'm working on doesn't do data access in a consistent way, and refactoring effort would be too great for the scope of the project and coming deadline.

How would I go with implementing a SQLCLR Trigger for Audit Trail? I would like it to be as simple as possible, and as easy to remove and replace with proper implementation later as possible.

I'm planning to write my audit to a single table (the database is not very write heavy), having columns like:

  • Timestamp ( datetime ) - when the change happened?
  • Username ( varchar ) - who made the change?
  • AffectedTableName ( varchar ) - which table has been affected?
  • AffectedRowKey ( varchar ) - this will be either a simple or compound key like ( Id=42 , A=4,B=2 )
  • OperationType ( char(1) ) - either I , U or D for insert, update and delete respectively.
  • InsertedXml ( xml ) - xml-serialized row ( SELECT * FROM INSERTED FOR XML AUTO )
  • DeletedXml( xml ) - xml-serialized row ( SELECT * FROM DELETED FOR XML AUTO )

I'm planning to query and resolve this data to a user-readable form in the application. I'm planning to implement this as a database trigger, written using SQLCLR. I can see 2 possible approaches:

  • Implement this entirely as SqlTrigger method:
  • Implement this as a SqlProcedure method taking parameters:
    • schemaName
    • tableName
    • insertedXml
    • deletedXml

I will appreciate any constructive criticism and suggestions. My limitation is that I have to implement the audit at the database level using triggers, and I want it to be as maintainable (read: removable and replacable) as possible. Also ideally, I don't want to have hundreds of triggers with exactly the same body, in case I have to modify them.

There is a serious restriction in SQLCLR triggers that will prevent you from implementing your audit triggers in SQLCLR: you can not find which parent object that was changed from inside a SQLCLR trigger. ie if you have a single SQLCLR trigger routine registered to multiple tables, you can not find which table got updated/inserted into/deleted from. At first sight @@procID may look usefull, however when called from inside a SQLCLR trigger, @@procid returns the same value, no matter which table was affected. I have searched the internet and experimented a lot and I have not found a solution. I have found more people having the same issue. Some of the messages date back as far as 2006.

I have created a feature request with Microsoft on Microsoft Connect. Please log in and press the UP arrow to get it implemented so you actually can use a SQLCLR trigger for your purpose: https://connect.microsoft.com/SQLServer/feedback/details/768358/a-sqlclr-trigger-should-be-given-the-parent-object-in-the-sqltriggercontext

I've been using a variation of this script to create audit triggers from some of my projects for awhile now with great results:

http://www.simple-talk.com/sql/database-administration/pop-rivetts-sql-server-faq-no.5-pop-on-the-audit-trail/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM