全局临时 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
下面的代码执行成功,除非我给它加上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