全局临时 table 作用域在存储过程中的行为不同

Global temporary table scope behaves differently inside a stored procedure

下面的代码执行成功,除非我给它加上create procedure dbo.proc_name ... as

use db_name
go

declare @sp_date date;
select @sp_date = getdate();

if object_id('tempdb..##global_tmp_tbl') is not null drop table ##global_tmp_tbl;

begin transaction

  set xact_abort on

  declare @query varchar(250), @exec_stmnt varchar(500);
  set @query = 'exec remote_db.dbo.remote_sp'  + ' ''''' + cast(@sp_date as varchar(10)) + ''''' ';
  set @query = '''' + @query + '''';

  set @exec_stmnt = 'select * into ##global_tmp_tbl from openquery(LS_RMT,' +  @query + ')';

  exec (@exec_stmnt);

commit transaction
go

if object_id('tempdb..#local_tmp_tbl') is not null drop table #local_tmp_tbl;
select * into #local_tmp_tbl from ##global_tmp_tbl;

这里LS_RMT是一个链接服务器,remote_sp是那个链接服务器上的数据库remote_db上的一个存储过程。

当我尝试将此代码放入存储过程时,SQL 服务器在链接服务器上执行存储过程后尝试从中读取时抱怨 ##global_tmp_tbl 是无效名称加载它。

我猜测全局临时 table 的范围在存储过程的上下文中改变了一次,但我找不到任何文档说明为什么会这样,所以我不确定。

这是一个范围问题,还是在从 openquery 语句加载它的事务中创建全局临时 table 之后,它实际上可以在存储过程中使用,而我正在做错了吗?

虽然我不完全确定为什么上面的代码在存储过程的上下文之外工作,但我确实确定在提交的事务中嵌入对全局临时 table 的所有引用允许存储过程工作。所以像下面这样:

use db_name
go

create procedure dbo.proc_name
@sp_date date = NULL

as
if isnull(@sp_date,'') = ''
begin
  select @sp_date = getdate();
end


if object_id('tempdb..##global_tmp_tbl') is not null drop table ##global_tmp_tbl;

begin transaction

  set xact_abort on

  declare @query varchar(250), @exec_stmnt varchar(500);
  set @query = 'exec remote_db.dbo.remote_sp'  + ' ''''' + cast(@sp_date as varchar(10)) + ''''' ';
  set @query = '''' + @query + '''';

  set @exec_stmnt = 'select * into ##global_tmp_tbl from openquery(LS_RMT,' +  @query + ')';

  exec (@exec_stmnt);

if object_id('tempdb..#local_tmp_tbl') is not null drop table #local_tmp_tbl;
select * into #local_tmp_tbl from ##global_tmp_tbl;

commit transaction
go