• I feel your pain and your boss' pain. Dealing with 3rd party application vendors is a huge pain especially when it seems that they break more stuff than they fix when they make a change.

    There's a fly in the ointment that's the size of Alaska with this request. Most applications aren't setup to use the credentials of the person that logged into the application. Rather, the application is given a login and that's the login that SQL Server (or any intercept application you could write) will see. Unless there's something in the data being passed to SQL Server by the application (perhaps a "ModifiedBy" field), then using even the ORIGINAL_LOGIN() function in T-SQL will only show that the application made the change. Even then, some ORMs will mess with multiple changes in that some ORMs won't send data that hasn't changed. That would affect things like a "ModifiedBY" field in that if the same person makes multiple changes, the "ModifiedBy" field won't contain a value or may be missing entirely.

    IF you can work around those problems, then here's what I would do.

    Write and "Instead Of" trigger on the table. It's a bit more complicated than a regular "After" trigger but it gives you a huge amount of control over what is allowed to affect the underlying table and it can do so without a ROLLBACK, which is quite expensive.

    This trigger would be setup to examine the conditions of the change-rows. If everything with the new "record" is hunky-dory, then write it to the final table. If the necessary columns aren't filled in properly, write that data to a permanent staging table (instead of the final table) with a DATETIME, a flag of some sort to identify it as a new "record", and a column that identifies what's wrong with the new "record". This would keep the transaction from holding everyone else up as the trigger would allow the transaction to complete immediately. The trigger could return an informational "error" to the app using RAISERROR but you have to be a little careful there. The use of RAISERROR could cause a ROLLBACK and that could rollback the row the trigger just saved to the staging table.

    Not being allowed to change the application means that the informational "error" message might not actually show up on the user screen. That leaves you with writing a job that regularly scans the staging table for new rows and sending an email to the person responsible for the row. Of course, that will also require some human handling/entry of data to correct the data on the row that's been sequestered in the staging table. Again, if the row can't be identified as to "who-dun-it", the process is pretty much dead in the water.

    There are a lot of caveats to any of the above, the worst, of course, being the fact that the app probably passes no "who-dun-it" information and probably doesn't reflect the original login because it uses its own login. Unless the app consistently passes user-identifying information with every change-row the, understanding all of the pain and expense in doing so, my recommendation would be to have someone fix the app.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)