私はこれを手順でやろうとしています:
DECLARE @a bit = 1;
BEGIN
SELECT * INTO #aTemp FROM OPENROWSET( ... );
IF @a = 0
BEGIN
SELECT ... INTO #bTemp FROM #aTemp;
END
ELSE
BEGIN
SELECT ... INTO #bTemp FROM #aTemp;
END
END
エラーが発生します:
Msg 2714, Level 16, State 1, Line 10
There is already an object named '#bTemp' in the database.
なぜこれが起こっているのですか?
更新
提案されたようにDROP
ステートメントを追加しようとしました here がまだ機能しません。
DECLARE @a bit = 1;
BEGIN
SELECT * INTO #aTemp FROM OPENROWSET( ... );
IF @a = 0
BEGIN
IF OBJECT_ID('[tempdb]..#bTemp') IS NOT NULL
BEGIN
DROP TABLE #bTemp;
END
SELECT ... INTO #bTemp FROM #aTemp;
END
ELSE
BEGIN
IF OBJECT_ID('[tempdb]..#bTemp') IS NOT NULL
BEGIN
DROP TABLE #bTemp;
END
SELECT ... INTO #bTemp FROM #aTemp;
END
END
ドキュメント :
単一のストアドプロシージャまたはバッチ内に複数の一時テーブルが作成される場合、それらは異なる名前を持つ必要があります。
次のように、IF
ブロックの前にテーブルを作成しました。
DECLARE @a bit = 1;
BEGIN
IF OBJECT_ID('[tempdb]..#bTemp') IS NOT NULL
BEGIN
DROP TABLE #bTemp;
END
CREATE TABLE #bTemp (
[c] int);
IF @a = 0
BEGIN
INSERT INTO #bTemp
SELECT 1 AS [c];
END
ELSE
BEGIN
INSERT INTO #bTemp
SELECT 1 AS [c];
END
DROP TABLE #bTemp;
END
これは質問への回答ではなく、##グローバル一時テーブルが同時実行性を強制終了する方法を@SebastienMeineにデモンストレーションするだけです。
1つのウィンドウで、次のようにします。
CREATE PROCEDURE dbo.floob1
@p INT
AS
BEGIN
SET NOCOUNT ON;
SELECT a = @p INTO ##floob;
END
GO
CREATE PROCEDURE dbo.floob2
AS
BEGIN
SET NOCOUNT ON;
SELECT a FROM ##floob;
END
GO
EXEC dbo.floob1 @p = 1;
WAITFOR DELAY '00:01:00';
EXEC dbo.floob2;
結果:
a
----
1
次に、別のウィンドウを開き、これを実行します。
BEGIN TRY
EXEC dbo.floob1 @p = 2;
END TRY
BEGIN CATCH
PRINT 'Something bad happened.';
END CATCH
GO
EXEC dbo.floob1 @p = 2;
GO
EXEC dbo.floob2;
結果:
何か悪いことが起こった。
メッセージ2714、レベル16、状態6、手順floob1
データベースにはすでに「## floob」という名前のオブジェクトがあります。
a
----
1
そのため、## tableは、それが作成されたプロシージャが終了してからずっと前から存在していますが、まだ存在しています。
次に、最初のウィンドウが終了したら、最初のウィンドウでこの部分をもう一度実行してみます。
EXEC dbo.floob1 @p = 1;
結果:
メッセージ2714、レベル16、状態6、手順floob1
データベースにはすでに「## floob」という名前のオブジェクトがあります。
そのため、同じユーザーが単に再度作成を試みたとしても、## tableはまだ存在しています。
これは次のことを示しています。
これは一時テーブルを事前に作成できず、コアロジックを動的SQLに配置したくない場合に使用するソリューションです。
IF 1 = 1 -- Replace with actual condition
BEGIN
SELECT * INTO #tmp1 FROM dbo.Table1
END
ELSE
BEGIN
SELECT * INTO #tmp2 FROM dbo.Table2
END
-- Inserting data into global temp table so sql server can't complain on not recognizing in a context
DECLARE @Command VARCHAR(MAX)
IF OBJECT_ID('tempdb..#tmp1') IS NOT NULL
BEGIN
SET @Command = 'SELECT * INTO ##tmp FROM #tmp1'
END
ELSE
BEGIN
SET @Command = 'SELECT * INTO ##tmp FROM #tmp2'
END
EXECUTE(@Command)
SELECT * INTO #tmpFinal FROM ##tmp -- Again passing data back to local temp table from global temp table to avoid seeing red mark
IF OBJECT_ID('tempdb..##tmp') IS NOT NULL DROP TABLE ##tmp
IF OBJECT_ID('tempdb..#tmp1') IS NOT NULL DROP TABLE #tmp1
IF OBJECT_ID('tempdb..#tmp2') IS NOT NULL DROP TABLE #tmp2
SELECT * FROM #tmpFinal
IF OBJECT_ID('tempdb..#tmpFinal') IS NOT NULL DROP TABLE #tmpFinal