web-dev-qa-db-ja.com

select ... intoに対してsp_executeSqlを実行しますが、一時テーブルデータを選択できません

Sp_Executedsqlの一時テーブル#TempTableを選択しようとしました。正常に挿入されたかどうかではなく、そこに書き込まれたメッセージ(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'.

動作が疑われるのは「選択」セクションのみです。挿入が機能していません。どのように修正しますか?

33
Worgon

ローカル一時テーブル#table_nameは現在のセッションでのみ表示され、グローバル一時##table_nameテーブルはすべてのセッションで表示されます。両方とも、セッションが終了するまで存続します。 sp_executesql-独自のセッションを作成します(Wordの「スコープ」の方が良いかもしれません)。

28
Michał Powaga

このシナリオでグローバル一時テーブルを使用すると、セッション間にテーブルが存在するため問題が発生し、呼び出しコードを非同期で使用する際に問題が発生する可能性があります。

ローカルの一時テーブルは、sp_executesqlを呼び出す前に定義されていれば使用できます。

CREATE TABLE #tempTable(id int);

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

SELECT * FROM #tempTable;
38
Rob Willis

@sql文字列には、into #TempTableを挿入しないでください。代わりに、SELECTステートメントなしでINSERTステートメントを呼び出します。

最後に、次のように結果を一時テーブルに挿入します。

INSERT INTO @tmpTbl EXEC sp_executesql @sql

また、このアプローチを使用する場合は、一時テーブルを宣言する必要があります

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

動的SQLの一時テーブルは、非動的SQL部分の範囲外です。

ここでこれに対処する方法を見てください: SQLサーバーのローカル一時テーブルに関するビット

7
Mladen Prajdic

一時テーブルは、それらを作成する接続が存在する間のみ存続します。意図せずに別の接続でselectを発行していると思われます。これを一時的に非一時的なテーブルに挿入し、データがそこにあるかどうかを確認することでテストできます。その場合は、元のソリューションに戻って、接続オブジェクトを必ず選択に渡してください。

3
Carth

これは私のために働いた

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

この問題を回避するには、sp_executesqlを実行する前に、最初にCREATE TABLE #TEMPTABLEコマンドを使用して空の一時テーブルを生成します。次に、sp_executesqlを使用してINSERT INTO #TEMPTABLEを実行します。これは機能します。これは、すべてのクエリが通常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