Выполните sp_executeSql для selectinto #table, но не можете выбрать данные временной таблицы

Пытался выбрать... во временную таблицу #TempTable в sp_Executedsql. Не успешно вставлено или нет, но там написано Сообщения (затронуто 359 строк), что означает успешную вставку? Скрипт ниже

DECLARE @Sql NVARCHAR(MAX);
SET @Sql = 'select distinct Coloum1,Coloum2 into #TempTable 
            from SPCTable with(nolock)
            where Convert(varchar(10), Date_Tm, 120) Between @Date_From And @Date_To';

SET @Sql = 'DECLARE @Date_From VARCHAR(10);
            DECLARE @Date_To VARCHAR(10);
            SET @Date_From = '''+CONVERT(VARCHAR(10),DATEADD(d,DATEDIFF(d,0,GETDATE()),0)-1,120)+''';
            SET @Date_To = '''+CONVERT(VARCHAR(10),DATEADD(d,DATEDIFF(d,0,GETDATE()),0)-1,120)+''';
            '+ @Sql;

EXECUTE sp_executesql @Sql;

После выполнения он возвращает мне сообщения (затронуто 359 строк). Далее при попытке выбрать данные из #TempTable.

Select * From #TempTable;

Его вернуть мне:

Msg 208, Level 16, State 0, Line 2
Invalid object name '#TempTable'.

Подозреваю, что он работает только с разделом «выбрать». Вставка не работает. как исправить?


person Worgon    schedule 07.11.2011    source источник


Ответы (8)


Локальная временная таблица #table_name видна только в текущем сеансе, глобальные временные таблицы ##table_name видны во всех сеансах. Оба живут, пока их сессия не будет закрыта. sp_executesql - создает свою сессию (может быть, слово "область действия" было бы лучше), поэтому это происходит.

person Michał Powaga    schedule 07.11.2011
comment
Я думаю, что слово "сфера" было бы лучше. DECLARE @sql NVARCHAR(MAX); SET @sql = 'SELECT @@SPID'; EXECUTE sp_executesql @sql; SELECT @@SPID - person Tom Hunter; 07.11.2011
comment
Спасибо @Michal, я уже вспомнил этот метод использования. Еще раз спасибо - person Worgon; 07.11.2011
comment
Вопрос был в том, как это исправить. Не зачем ломать. Ниже я дал правильный ответ. INSERT INTO @tmpTbl EXEC sp_executesql @sql - person Mark Entingh; 21.11.2017
comment
Примечание. sp_executesql не создает собственный сеанс. Вместо этого он создает свой собственный пакет (или контекст выполнения). Временные таблицы могут просматриваться другими пакетами в том же сеансе. Однако, поскольку они удаляются при выходе создавшего их пакета, практически говоря, их могут видеть только подчиненные пакеты (т. е. контексты выполнения, созданные тем же контекстом, который создал таблицу Temp). - person RBarryYoung; 21.08.2018
comment
Нет ли проблемы, что если несколько человек попытаются запустить процесс, который использует эти глобальные переменные, мы получим взаимоблокировки и другие проблемы. - person Elizabeth; 18.10.2018

Использование глобальной временной таблицы в этом сценарии может вызвать проблемы, поскольку таблица будет существовать между сеансами, и может привести к некоторым проблемам при асинхронном использовании вызывающего кода.

Можно использовать локальную временную таблицу, если она определена до вызова sp_executesql, например.

CREATE TABLE #tempTable(id int);

sp_executesql 'INSERT INTO #tempTable SELECT myId FROM myTable';

SELECT * FROM #tempTable;
person Rob Willis    schedule 10.08.2012

В строку @sql не вставляйте into #TempTable. Вместо этого вызовите свой оператор SELECT без оператора INSERT.

Наконец, вставьте результаты во временную таблицу следующим образом:

INSERT INTO @tmpTbl EXEC sp_executesql @sql

Кроме того, вам нужно будет объявить временную таблицу, если вы используете этот подход.

DECLARE @tmpTbl TABLE (
    //define columns here...
)
person Mark Entingh    schedule 02.05.2017
comment
Хотя это может работать, как написано, оно неполно. Проблема в том, что в исходном примере OP select ... into ... #TempTable ... фактически создаст временную таблицу, включая динамическое указание столбцов. Чтобы ваш оператор работал, временная таблица (или табличная переменная, как вы ее используете) должна быть создана/объявлена ​​первой (вместе с правильными/совпадающими спецификациями столбца). - person RBarryYoung; 21.08.2018
comment
Ах да, я забыл упомянуть об этом. Вам нужно будет сначала объявить свою временную таблицу. - person Mark Entingh; 23.08.2018

ваша временная таблица в динамическом SQL выходит за рамки нединамической части SQL.

Посмотрите, как с этим справиться: Немного о локальных временных таблицах сервера sql

person Mladen Prajdic    schedule 07.11.2011

Временные таблицы существуют только до тех пор, пока создается соединение, которое их создает. Я ожидаю, что вы непреднамеренно выдаете выбор для отдельного соединения. Вы можете проверить это, на мгновение выполнив вставку в невременную таблицу и посмотрев, есть ли там ваши данные. Если это так, вы можете вернуться к своему исходному решению и просто обязательно передать объект подключения в свой выбор.

person Carth    schedule 07.11.2011
comment
Это не совсем так. При использовании таких вещей, как PreparedStatements, механизм MSSQL запускает его через хранимую процедуру для выполнения, что означает, что любые временные таблицы сохраняются для контекста хранимой процедуры, и если вы попытаетесь выполнить PreparedStatement с последующим выбором * из tempTable, вы получить tempTable не найден. - person Chris Knoll; 22.02.2019

Это сработало для меня

declare @sql nvarchar(max)     
create table #temp ( listId int, Name nvarchar(200))     
set @sql = 'SELECT top 10 ListId, Name FROM [V12-ListSelector].[dbo].[List]'    
insert into #temp
exec sp_executesql  @sql    
select * from #temp    
drop table #temp
person WebBoy    schedule 21.08.2018

Чтобы обойти эту проблему, используйте команду CREATE TABLE #TEMPTABLE, чтобы создать пустую временную таблицу перед запуском процедуры sp_executesql. Затем запустите INSERT INTO #TEMPTABLE с помощью sp_executesql. Это сработает. Вот как я преодолеваю эту проблему, поскольку у меня есть настройка, в которой все мои запросы обычно выполняются через sp_executesql.

person Simon Darlow    schedule 22.03.2016

Это сработало для меня:

DECLARE @Query as NVARCHAR(MAX);
SET @Query=(SELECT * FROM MyTable) ;
SET @Query=(SELECT 'SELECT * INTO dbo.TempTable FROM ('+@Query +') MAIN;');
EXEC sp_executesql @Query;

SELECT * INTO #TempTable FROM dbo.TempTable;
DROP TABLE dbo.TempTable;
SELECT * FROM #TempTable;
person Hpeck    schedule 28.02.2021