我用临时表修改了一些sp,以消除每个sp中的数十个declare @vars
。单独运行,它们似乎运行良好,直到我编写了一个测试用例脚本,然后遍历生产系统中的实时记录以测试这些未发布的新sps(ATM,我想不出更好的方法来遍历参数集来对其进行测试。没有光标的地方。请尽量不要在此处重点关注光标的使用)。重复exec
期间我得到了不同的结果。
例如
-- 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
结果就像
| param1 | print |
| value1 | cond1 = 1 do A |
| value1 | cond1 = 0 do B |
| value2 | cond1 = 0 do B |
| value1 | cond1 = 0 do B |
实时数据各不相同,但始终遵循相同的模式。在第一个cond1为true之后,以下exec将全部导致cond1 =0。即使cond1为true。
在第一个成功的select into
之后,显然select into
失败了。 SP2或SP1终止后,临时表不会释放。
在此,本地#temp_sp2
是在sp2的范围内而不是从外部范围创建的,一旦调用返回,创建范围将不再有效,但表将不被释放。感觉到后者对同一sp的调用与先前的调用具有相同的作用域。
我已经知道以下内容:
我的问题是关于他们的寿命。通常,一旦创建了对象,它就绑定到本地函数作用域,一旦作用域消失,该对象就会被GCed。在此嵌套sp中创建的本地临时表显然不遵循此要求。
这里的陷阱是什么,当对范围的常规理解不适用(例如python)时,应如何使用它。
Scope of temporary tables in SQL Server
的答案实际上与此矛盾。
此外,在过程结束时也无需删除表(从 再次相同的链接):
存储过程完成后,将自动删除在存储过程中创建的本地临时表
从@ Panagiotis-Kanavos的评论中,我似乎了解到temp表(确切地说是它们的奇特别名映射,不一定是真实表)具有可见性/创建范围,但直到会话结束。这可以解释事情,但与建议问题的答案中的先前陈述相矛盾。
范围和生命周期并不真正适用。 SQL不是C#。 #somename是在执行create table语句时创建的真实表,并且只要会话/连接处于打开状态就存在。
现在我更困惑了...
答案 0 :(得分:0)
根据我的经验,#temp_table的范围在当前会话中。因此,只要单独执行这些SP,就可以了。但是,如果将SP作为同一脚本的一部分执行,则#temp_tables可能在脚本内具有作用域。
我的建议是在SP中创建和 DROP 。这是每次#temp_table是由同一脚本中的单独SP创建的,每次都会重新创建。