web-dev-qa-db-fra.com

Exécutez sp_executeSql pour select ... dans #table mais ne pouvez pas sélectionner les données de la table temporaire

J'essayais de sélectionner ... dans une table temporaire #TempTable dans sp_Executedsql. Ce n'est pas inséré avec succès ou pas, mais il y a des messages écrits (359 lignes affectées) qui signifient que l'insertion a réussi? Script ci-dessous

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;

Une fois exécuté, il me renvoie des messages (359 ligne (s) affectée (s)). Ensuite lorsque vous essayez de sélectionner les données de #TempTable.

Select * From #TempTable;

Son retour me:

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

Suspecté son fonctionnement uniquement la section "sélectionner" uniquement. L'insert ne fonctionne pas. comment y remédier?

33
Worgon

Table temporaire locale #table_name est visible uniquement dans la session en cours, global temporaire ##table_name les tables sont visibles dans toutes les sessions. Les deux vivent jusqu'à la clôture de leur session. sp_executesql - crée sa propre session (peut-être que Word "scope" serait mieux), c'est pourquoi cela se produit.

28
Michał Powaga

L'utilisation d'une table temporaire globale dans ce scénario peut provoquer des problèmes car la table existe entre les sessions et peut entraîner certains problèmes d'utilisation asynchrone du code appelant.

Une table temporaire locale peut être utilisée si elle est définie avant d'appeler sp_executesql, par ex.

CREATE TABLE #tempTable(id int);

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

SELECT * FROM #tempTable;
38
Rob Willis

Dans votre @sql chaîne, n'insérez pas into #TempTable. Appelez plutôt votre instruction SELECT sans instruction INSERT.

Enfin, insérez les résultats dans votre table temporaire comme suit:

INSERT INTO @tmpTbl EXEC sp_executesql @sql

En outre, vous devrez déclarer la table temporaire si vous utilisez cette approche

DECLARE @tmpTbl TABLE (
    //define columns here...
)
11
Mark Entingh

votre table temporaire en SQL dynamique est hors de portée dans la partie SQL non dynamique.

Regardez ici comment gérer cela: n peu sur les tables temporaires locales du serveur SQL

7
Mladen Prajdic

Les tables temporaires ne vivent que le temps de la connexion qui les crée. Je m'attendrais à ce que vous émettez involontairement la sélection sur une connexion distincte. Vous pouvez tester cela en faisant momentanément votre insertion dans une table non temporaire et en voyant si vos données sont là. Si tel est le cas, vous pouvez revenir à votre solution d'origine et assurez-vous simplement de passer l'objet de connexion à votre sélection.

3
Carth

Cela a fonctionné pour moi

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
1
WebBoy

Pour contourner ce problème, utilisez d'abord une commande CREATE TABLE #TEMPTABLE pour générer une table temporaire vide avant d'exécuter sp_executesql. Exécutez ensuite INSERT INTO #TEMPTABLE avec sp_executesql. Cela fonctionnera. C'est ainsi que je surmonte ce problème car j'ai une configuration dans laquelle toutes mes requêtes sont généralement exécutées via sp_executesql.

1
Simon Darlow
declare @sql varchar(1000)
set @sql="select * into #t from table;"
set @sql =@sql + "select * from #t;"

 execute  SP_EXECUTESQL  @sql
1