I'm having a general discussion with one of my developers about philosophy of structuring TSQL stored procedures.
Let's make a couple assumptions (to avoid responses along the line of "don't put business logic in SPs", etc):
- Business Logic can be in SPs
- There is no standard scripted layer of CRUD SPs
- Complex procedures are executed in single scope within an SP
- Dynamic SQL is allowed
Essentially my coworker has hit his head against the SQL Server wall of nested inserts in SQL Server. You can nest them beyond a single level.
i.e. :
PROC C is called by PROC B, the results of which are INSERTED into a temp table #X and operations are performed and then a result set is returned
PROC B is called by PROC A, the results (our original final select from PROC C + Transformations) of which are INSERTED into a temp table #Z and operations are performed and then a result set is returned
This results in SQL Server throwing an error saying you can't nest inserts into temp tables.
I agree with this logic, assuming our four original premises, it would then simply be permissible to include the logic executed in PROC C directly in PROC B.
My coworker however feels, being a good Object Orientated encapsulator, that by encapsulating the final nested insert the code is more maintainable.
I on the other hand feel that encapsulating code into CRUD operations, which use temp tables, is fundamentally opposed to the declarative and procedural approach to data management inherent in SQL and relational databases.
Ultimately, his argument is that if the logic was simply in one SP, then should the table schema change, all SPs addressing the table would have to change. A valid point, however I feel that is unlikely as once our development has bedded down tables are not subject to ad-hoc change.
My argument is that by encapsulating temp table inserts, for use in n-th degree nesting (if possible - thankfully its not), would result in a case in which all SPs which call that encapsulated procedure (or should we now rather call it a method?) would have to be retested anyway in the event that the centralized encapsulated procedure changes, since unless its outputs are the same, it may well result in a break in the calling parent SP.
I suppose my ultimate question is this, fundamentally is T-SQL a declarative, a procedural or an imperative language. In my opinion it is clearly a mixture --> I suppose if I had to create the recipe I'd say:
10% Declarative (since in principle its declarative) 70% Procedural (In our case, the case in which business processes are in procs) 20% Imperative (Imperative constructs exist - esp. in newer SQL Server versions)
p.s. At the moment he's suggesting using OUTPUT parameter in the SP call, rather than:
insert into #temp exec spInsertUpdateTable
I have a whole other dislike for OUTPUT parameters, but I suppose that might have to fly. Any other suggestions?