1

I revised some of the sp with temp table to eliminate the dozends of declare @vars in each sps. Runing individually, they seem to work great, until I wrote a test case script, looping over the live records in production system to test these unreleased new sps (ATM, I can't think of better ways to loop through parameter sets to test them without a cursor. Please try not to focus on use of cursor here). I got different result during repeated exec. e.g.

-- sub_sp2: 
-- sub_task2
select top 1 col1, col2, .... col30 
       into #temp_sub_sp2 
from tb1
left join tbl_ext1 
left join tbl_ext2
left join tbl_ext3
left join tbl_ext....
where cond1 = true

if @@row_count < 0 
    print cond1=true do A thing
else 
    print cond1=false do B thing

-- sp1: 
-- this is a master sp with a couple of sub tasks written in sub_sps.

exec sub_sp2 param1,...., @task2_result output
exec sub_sp3 param1,...., @task3_result output
exec sub_sp4 param1,...., @task4_result output
-- do sth with @result1

-- test script:
-- a test script to call sp1 repeatedly with 
-- different parameters from production system to check result.
declare cur1 ...
   for select colx from prd_mach_status
open cur1
fetch next from cur1 into @param1
...
while ...
    exec sp1 @param1

The result is like

| param1 | print          |
| value1   | cond1 = 1 do A |
| value1   | cond1 = 0 do B |
| value2   | cond1 = 0 do B |
| value1   | cond1 = 0 do B |

The live data varies, but always follow the same pattern. After the 1st cond1 is true, the following exec will all result in cond1 = 0. Even if cond1 is true.

Clearly the select into failed, after the first successful select into. and the temp table is not freed after SP2, or SP1 has terminated.

Here the local #temp_sp2 is created inside sp2's scope, not from outer scope, once the call returns, the creation scope is no longer valid, but the table is not freed. It feels like the latter call to the same sp shares the same scope with the previous calls.

I already know the following :

  • Temp tables are just aliased tables with fancy names in tempdb.
  • The concept of scopes defines their visibility
  • Sessions are top level scopes seperated per connection.

My question is about their lifespan. Usually once an object is created its bound to a local function scope, once the scope is gone, the object is GCed. The local temp table created in a nested sp here clearly didn't follow this.

What is the catch here, how should it be used, when the regular understanding of scope doesn't apply here (e.g. python).

The answer from Scope of temporary tables in SQL Server actually contradicts with this.

Also, there's no need to DROP TABLE at the end of your procedure (from same link again):

A local temporary table created in a stored procedure is dropped automatically when the stored procedure is finished

From @Panagiotis-Kanavos 's comment, I seem to get the idea that temp table (to be exact their fancy alias mapping, not necessarily the real table) has a scope for visibility/creation but is not auto destroied until the session ends. This explains things, but controdicts with previous statements from suggested question's answer.

Scope and Lifetime don't really apply. SQL isn't C#. #somename is a real table that's created when a create table statement is executed and exists as long as the session/connection is open.

Now I am more confused...

Ben
  • 1,133
  • 1
  • 15
  • 30
  • 3
    Possible duplicate of [Scope of temporary tables in SQL Server](https://stackoverflow.com/questions/18614344/scope-of-temporary-tables-in-sql-server) – Cee McSharpface Sep 19 '18 at 10:18
  • `Scope` and `Lifetime` don't really apply. SQL isn't C#. `#somename` is a real table that's created when a `create table` statement is executed and exists as long as the *session/connection* is open. The difference between local and global tables is who can access them. Besides, SQL is a set-based language. You don't need cursors to work on data or temporary tables to pass data between stored procedures. What are you trying to do? – Panagiotis Kanavos Sep 19 '18 at 10:20
  • If you really want to pass data from one stored procedure to another you could use a Table Valued Type. It would still be awkward compared to a proper query or view – Panagiotis Kanavos Sep 19 '18 at 10:22
  • 1
    @Ben, can you add the complete script to your question that demonstrates this? Temp table created within a proc should be dropped when the proc completes. – Dan Guzman Sep 19 '18 at 10:48
  • Not passing anything anywhere. The orignal sp is cluttered by dozes of declares. The same group of table is accessed multiple times to retrived different values. They share the same primary key. so I decided to create a single row #temp table to replace the variables; that all values are retrived in one go; replaced the 'if ... then ...'s. with 'select .. where...'. – Ben Sep 19 '18 at 11:35
  • Thank you, all. OK. I'll drop the #temp table at the end of each sp. One more question, could there be any possible concurrency problem with this aproach. since there is no scoped related lifespan of local temp tables ? – Ben Sep 19 '18 at 11:38
  • @dlatikay: I think your linked answer said `Also, there's no need to DROP TABLE at the end of your procedure (from same link again).` while @Habeeb, @Panagiotis Kanavos seem to suggest the opposite. what should I do ? – Ben Sep 19 '18 at 11:43
  • 1
    include a minimal, complete example in your question, which we can use to actually reproduce the issue. or go modernize with @table variables. select...into is no longer possible there, but you improve on maintainability when you're forced to declare your temporary tables. – Cee McSharpface Sep 19 '18 at 11:49
  • @dlatikay: Your request is valid. I inspected the chain of scripts again to simplify it. There is a nasty typo in the test script. The SPs are OK. Thanks. – Ben Sep 19 '18 at 13:59
  • @DanGuzman: You are right they indeed get dropped like scoped local variables. Though I split them into multiple sub_sps the script is still too long. I tried to smiplify the case, now I see there is a bug in testing script Thanks. – Ben Sep 19 '18 at 14:10

1 Answers1

0

From my experience, the scope of a #temp_table is within the current session. So as long as the SPs are executed individually, its fine. But when the SPs are executed as part of the same script, the #temp_tables could have scope within the script.

My suggestion is to CREATE and DROP the #temp_table within the SP. This was each time, the #temp_table is created by separate SPs in the same script, it will be recreated each time.

Habeeb
  • 7,601
  • 1
  • 30
  • 33