views:

327

answers:

2

I have a trigger that will be dynamically created, as it will be attached to a view that is also dynamically generated. I don't want my stored procedure to have the entire trigger within it, so I would like to move most of it to a stored procedure, but I won't know the fields in the inserted and deleted tables.

The trigger is about 90 lines long, and the only part I really need to be different between triggers is:

DECLARE @DEBUG bit = 1
DECLARE @EntityName nvarchar(128) = 'Lot'
 SELECT * INTO #MYINSERTED FROM INSERTED
 SELECT * INTO #MYDELETED FROM DELETED

If I could move the rest of it to a stored procedure then that would be great.

The problem with just passing in the @DEBUG and @EntityName and using #MYINSERTED and #MYDELETED in the stored procedure then I would have a problem if two people are inserting or updating the same view at the same time.

The best bet would be to pass a table variable to remove any concurrency issues but I am not certain the best way to do that.

Thank you.

+1  A: 

This would actually be a bad idea. SQL is not like your run-of-the-mill procedural language. The SQL 'compilation' binds to a physical access path plan, meaning that the statements are compiled into plans that say 'open rowset with ID 1234, seek a record and retrieve its content' and that '1234' is determined during the compilation of a batch by the optimizer. Which means that moving common code into a procedure as you plan more often hurts more than it benefits. The procedure cannot be bound to a 'generic' access path, it needs to know the actual tables and objects it should look into for selects and updates and the like. You either end up doing dynamic SQL in the procedure or moving only non data bound, generic, parts of the procedure (eg. calculations) which creates very convoluted code and still can hurt performance while at the same time decreasing the procedure readability.

Much more advisable is to have a template and generate your triggers from these template via various code generation techniques, like XML and XSLT.

Remus Rusanu
I have a great deal of dynamic sql in the trigger, as the tables that will be involved are not known until the insert/update is done. I would like the dynamic sql to be in the stored procedure, as I would prefer my trigger to be as simple as possible, as I find stored procedures easier to test.Can a stored procedure generate a trigger from XML and XSLT? All of this happens in the database, I can't have any of it happen at a higher level.
James Black
You could hook your trigger generation to a DDL trigger (http://msdn.microsoft.com/en-us/library/ms190989.aspx) and generate the non-dynamic trigger just in time in response to creation of a table.
Remus Rusanu
btw if you cannot generate the trigger right inside the DDL trigger because of various reasons (transactional context, references not yet available) you can use event notifications (http://msdn.microsoft.com/en-us/library/ms182602.aspx) instead if you can tolerate a small period of the table being 'exposed' (ie. no trigger linked to it) right after is created/altered.
Remus Rusanu
A: 

I suspect the metadata/schema about inserted and deleted are the core problem here (which is why you are using SELECT * INTO).

If you are code generating the trigger and view dynamically, I would say it probably doesn't make much difference. After all, all the triggers and views are code generated and can be regenerated as your system gets new capabilities or the core SP is improved.

Only if the triggers and views are customized and are never regenerated, then there would be a benefit of sharing a core SP which can be modified and upgraded instead of regenerating the views and triggers.

The overhead of regenerating is probably outweighed by generated code which will have a solid execution plan and better binding.

Cade Roux
I don't expect the main part of the trigger to be reworked, and if it is, it would be simpler to have one stored procedure fixed so all the referring triggers get the new change, as a side-effect.My concern is that you are correct in it may be simpler to just keep the trigger together and dynamically generate the entire thing, but I am hoping there is a better solution. If nothing else I may see if the stored procedure that creates the view/trigger can get the sql from a file and change the value of @EntityName, as that is the only difference between the tables.
James Black
Your SP that generates the code can do anything. I have SPs that insert rows in control tables, create SPs and tables for those SPs to use and everything. The SP basically generates an entire framework for a particular process based on a template.
Cade Roux