Answers:
尽管Brent的回答对于所有实际目的都是正确的,这不是我见过的人担心的事情,但会话中存储过程的多次调用有可能通过会话范围的#temp表相互影响。
好消息是它极不可能在野外发生,因为
1)在存储过程或嵌套批处理中声明的#Temp表实际上没有会话可见性(或生存期)。这些是迄今为止最常见的情况。
2)它要求 MultipleActiveResultsets和一些非常奇怪的异步客户端编程,或者用于存储过程在中间返回结果集,并且客户端在处理第一个结果的同时调用存储过程的另一个实例。
这是一个人为的例子:
using System;
using System.Data.SqlClient;
namespace ado.nettest
{
class Program
{
static void Main(string[] args)
{
using (var con = new SqlConnection("Server=localhost;database=tempdb;integrated security=true;MultipleActiveResultSets = True"))
{
con.Open();
var procDdl = @"
create table #t(id int)
exec ('
create procedure #foo
as
begin
insert into #t(id) values (1);
select top 10000 * from sys.messages m, sys.messages m2;
select count(*) rc from #t;
delete from #t;
end
');
";
var cmdDDL = con.CreateCommand();
cmdDDL.CommandText = procDdl;
cmdDDL.ExecuteNonQuery();
var cmd = con.CreateCommand();
cmd.CommandText = "exec #foo";
using (var rdr = cmd.ExecuteReader())
{
rdr.Read();
var cmd2 = con.CreateCommand();
cmd2.CommandText = "exec #foo";
using (var rdr2 = cmd2.ExecuteReader())
{
}
while (rdr.Read())
{
}
rdr.NextResult();
rdr.Read();
var rc = rdr.GetInt32(0);
Console.WriteLine($"Numer of rows in temp table {rc}");
}
}
Console.WriteLine("Hit any key to exit");
Console.ReadKey();
}
}
}
哪个输出
Numer of rows in temp table 0
Hit any key to exit
因为存储过程的第二次调用插入了一行,然后在第一次调用等待客户端从其第一个结果集中获取行时,从#t中删除了所有行。请注意,如果第一个结果集较小,则行可能会被缓冲,执行可能会继续而不会向客户端发送任何内容。
如果您移动
create table #t(id int)
输出到存储过程中:
Numer of rows in temp table 1
Hit any key to exit
并与临时表声明中的程序,如果你改变了第二次查询
cmd2.CommandText = "select * from #t";
它失败并显示:
'无效的对象名称'#t'。
因为在存储过程或嵌套批处理中创建的#temp表仅在该存储过程或批处理及其调用的嵌套过程和批处理中可见,并且在该过程或批处理结束时被销毁。