【问题标题】:Can you use #Temp table in dynamic SQL when in OPENROWSET?在 OPENROWSET 中可以在动态 SQL 中使用#Temp 表吗?
【发布时间】:2020-02-06 05:53:24
【问题描述】:

我正在尝试在 Microsoft SQL Server 2014 的动态 SQL 中使用 #Temp 表,它在本地运行良好,但如果我将它放在 OPENROWSET 中以便我可以从另一台服务器收集数据,则会出现错误:

返回链接服务器“(null)”的 OLE DB 提供程序“SQLNCLI11” 消息“延迟准备无法完成。”。消息 8180,级别 16, State 1, Line 9 Statement(s) 无法准备。消息 208,级别 16,状态 1,第 9 行无效的对象名称 '#RefmdCodeList'

这是不允许的吗?或者有什么不同的方法我需要这样做?

为了简化问题,这里有两个例子。
这可行:

declare @sql nvarchar(max) 
set @sql =  N' select * from #RefmdCodeList'
exec(@sql)

这不起作用:

declare @sql nvarchar(max) 
set @sql = N'   SELECT * FROM
                    OPENROWSET(''SQLNCLI'', 
                    ''Server=' + @PAFServer + ';Database=' +@PAFDatabase +';UID=p2kservices;PWD=P0werP@th!'',
                      N'' SELECT * from #RefmdCodeList'')'
exec(@sql)

对于可能会问的人,以下是我真正想做的事情。如果我删除#Temp 表,我的代码如下所示运行良好。包含#Temp 表后,我收到上面的错误消息。

declare @sql nvarchar(max) 
set @sql = N'   SELECT * FROM OPENROWSET(''SQLNCLI'', ''Server=' + @PAFServer + ';Database=' +@PAFDatabase +';UID=p2kservices;PWD=P0werP@th!'',
N'' ;WITH spec_data (entity, accession_no, acc_id, spec_id, spec_description, spec_label, spec_sc_code) AS
(SELECT ''''PAMF'''' AS entity, a.accession_no, a.id, asp.id, asp.description, asp.specimen_label, substring(''''88''''+spec_sc.code, 1,5)
FROM accession_2 a (NOLOCK)
JOIN acc_specimen asp (nolock) ON asp.acc_id = a.id
LEFT OUTER JOIN acc_charges spec_ac (NOLOCK) on spec_ac.acc_id = asp.acc_id 
        AND spec_ac.rec_id = asp.id AND spec_ac.rec_type = ''''S''''
LEFT OUTER JOIN service_code spec_sc (NOLOCK) on spec_sc.id = spec_ac.service_code_id
JOIN acc_refmd aref (NOLOCK) ON aref.acc_id = a.id
WHERE recv_date >= ''''+CONVERT(VARCHAR(10),@SDate, 101) +'''' and recv_date < ''''+CONVERT(VARCHAR(10),@EDate, 101)+''''
AND aref.refmd_id in (SELECT id from #RefmdCodeList)
) 
SELECT DISTINCT entity accession_no, asp.acc_id, spec_id, spec_description, spec_label, 
    spec_sc_code, substring(''''88''''+lab_sc.code, 1,5)
FROM spec_data asp
LEFT OUTER JOIN acc_charges lab_ac (NOLOCK) on lab_ac.acc_id = asp.acc_id and rec_type = ''''L''''
JOIN service_code lab_sc (NOLOCK) on lab_sc.id = lab_ac.service_code_id
JOIN acc_order ord (NOLOCK) on ord.id = lab_ac.rec_id 
        AND ord.acc_specimen_id = asp.spec_id
WHERE substring(''''88''''+spec_sc.code, 1,5) in (SELECT service_code from #ServiceCodeList) 
OR substring(''''88''''+lab_sc.code, 1,5) in (SELECT service_code from #ServiceCodeList)
'') '

【问题讨论】:

  • 临时表仅在本地会话中可见。它在链接服务器查询中不可用。

标签: sql-server tsql


【解决方案1】:

这是不允许的吗?

#temp 表仅对当前正在运行的会话可见。即使到本地服务器的 openrowset() 也不会看到 #temp 表,因为 openrowset 在不同的连接(和另一个会话)上执行。

或者我需要一些不同的方法吗?

您可以在远程服务器上填充临时表并使用该临时表假装/好像它是一个#table。用于传递值的通用暂存表(带有一个 int 列和一个 varchar 列)工作得很好。为了区分并行进程,暂存表可以有一个 sessionid 列(它在本地保存 @@spid)。

为了灵感......

--local temp table
create table #localtemp
(
    srvcode varchar(100)
);
insert into #localtemp(srvcode)
select @@servername + '-' + name
from sys.objects;

--populate a proxy table on the remote server
declare @foo int;
select @foo = objectid
from openrowset('SQLNCLI', 'Server=Universe;Trusted_Connection=yes', 
'set fmtonly off;

if object_id(''tempdb.dbo.proxyservicetable'') is null
begin
    create table tempdb.dbo.proxyservicetable
    (
        sessionid smallint,
        servicecode varchar(100)
    );

    create clustered index uclxproxyservicetable on tempdb.dbo.proxyservicetable(sessionid);
end

select object_id(''tempdb.dbo.proxyservicetable'') as objectid;
');

select @foo as stagingtableobjectid --on the remoteservers

--cleanup any staging leftovers from previous executions
delete from
openrowset('SQLNCLI', 'Server=Universe;Trusted_Connection=yes', 
'
select *
from tempdb.dbo.proxyservicetable;
')
where sessionid = @@spid;

--populate staging with values from the current execution (#localtemp as source)
insert into
openrowset('SQLNCLI', 'Server=Universe;Trusted_Connection=yes', 
'
select *
from tempdb.dbo.proxyservicetable;
')
select @@spid, srvcode
from #localtemp;

--passthrough query, at the remote server
declare @sql nvarchar(max)
select @sql = 'select *
from openrowset(''SQLNCLI'', ''Server=Universe;Trusted_Connection=yes'', 
'' select @@servername,* from tempdb.dbo.proxyservicetable where sessionid =' + cast(@@spid as varchar(10)) + '''
)';
exec(@sql);
go

drop table #localtemp
go

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-26
    • 2016-01-06
    • 2015-05-03
    • 2012-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多