我不明白为什么当涉及临时表以及和 时,某些 SQL 杠杆作用sp_executesql
会如此工作。我正在使用 SQL Server。INSERT
SELECT - INTO
以下是有问题的代码:
-- Insert into
CREATE TABLE #results
(
rid INT,
);
declare @sql nvarchar(max) = '';
set @sql = 'INSERT INTO #results (rid) VALUES (1);';
EXEC sp_executesql @sql;
select * from #results;
-- Select into
CREATE TABLE #results2
(
rid INT,
);
declare @sql2 nvarchar(max) = '';
set @sql2 = 'select rid into #results2 from #results;';
EXEC sp_executesql @sql2;
select * from #results2;
-- Clean up
drop table #results;
drop table #results2;
运行时,#results 只有一行rid = 1
,而 #results2 根本没有行,您可以在此处看到:
说实话,我对此有几个困惑。首先,我预计会SELECT - INTO
失败,因为此会话中应该已经存在一个名为 #results2 的表。
sp_executesql
您可以通过以下类似的 SQL 代码看到此错误,该SQL 代码未利用SELECT - INTO
:
-- Insert into
CREATE TABLE #results
(
rid INT,
);
declare @sql nvarchar(max) = '';
set @sql = 'INSERT INTO #results (rid) VALUES (1);';
EXEC sp_executesql @sql;
select * from #results;
-- Select into
CREATE TABLE #results2
(
rid INT,
);
declare @sql2 nvarchar(max) = '';
select rid into #results2 from #results;
select * from #results2;
-- Clean up
drop table #results;
drop table #results2;
正如预期的那样,此代码会产生错误:
数据库中已存在一个名为“#results2”的对象。
根据此答案,我假设发生这种情况是因为sp_executesql
有自己的会话。 因此,SELECT - INTO
嵌套的内部sp_executesql
不知道 #results2 存在,因此它创建了自己的临时表,名为 #results2,将其插入其中,然后删除该表。
这对我来说很有意义,除了,在那个相同的中sp_executesql
访问表#results。所以sp_executesql
知道#results表,但不知道#results2表?另外,我的第一个sp_executesql
with thanINSERT
也没有访问#results表的问题。基于此commnet,似乎sp_executesql
可以访问#results的原因是因为sp_executesql
实际上创建了自己的批处理,并且同一会话中的批处理可以看到彼此的临时表。很好,除了然后我们回到我最初的困惑,为什么sp_executesql
在运行时没有抱怨#results2的存在SELECT - INTO
?
如果一定要概括的话,我感到困惑的核心点是:
SELECT - INTO
为什么嵌套的内部不会sp_executesql
抛出#results2 已存在的错误?- 为什么
INSERT
嵌套在里面的语句sp_executesql
可以毫无问题地访问#results 并将其插入其中? - 为什么
SELECT - INTO
嵌套的内部sp_executesql
访问#results没有问题,但似乎无法识别#results2的存在?