2011-01-28 5 views
6

背景:指定された名前のテンポラリテーブルで「stuff」するストアドプロシージャがあります。プロシージャは、テンポラリ・テーブルのスキーマを検査し、スキーマに応じて異なる「stuff」を実行するという点で一般的です。私はこれがちょっと変わっていることを理解していますが、それ以外のほとんどの状況で問題なく動作するので、私は変更したくありません....Temp Tableが存在しないときにTemp Tableが存在するとSQL Serverが判断するのはなぜですか?

私は一時テーブル用に2つの異なるスキーマを作成するストアドプロシージャ同じ名前。論理的には、IFのどのブランチに応じて1つの一時テーブルしか作成しません。問題はSPROCがSQL Serverによって確認されたとき、それはIFの両側評価しているように思えることです

だから、このSQLは失敗した(これはSQLの構文をチェックするなら意味があります。):

IF (1=1) 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL 
    ) 
END 
ELSE 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL, 
     c BIGINT NOT NULL 
    ) 
END 

--exec SomeProcedureWhichDoesStuffWith#Test 

DROP TABLE #test 
を次のエラーと

:SQLチェッカーを満たすように思わ

Msg 2714, Level 16, State 1, Line 14
There is already an object named '#test' in the database.

IFS内部のドロップテーブルのない組み合わせ(作成、テーブルのDDLの前または後に)。

どうすればいいですか?たとえば、構文チェックを行わないようにSQLに指示し、sprocをそのまま受け入れることはできますか?

答えて

6

これは制限です。 #tmpは新しいセッションで作成され、すぐに失われるため、動的SQLは機能しません。示すように、EXACTスニペットの場合、これは、2つの同じバッチ内.. #NAMEを作成するのではなく、私はいけないので、これはまた、一般的な形で

IF (1=1) 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL 
    ); 
END 
GO 

IF NOT (1=1) 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL, 
     c BIGINT NOT NULL 
    ) 
END 
0

に動作します

CREATE TABLE #test 
(
    a BIGINT NOT NULL, 
    b BIGINT NOT NULL 
) 

IF not (1=1) 
    ALTER TABLE #test ADD c BIGINT NOT NULL 

同じように存在することはできませんありません。 SQL 2008を持って、私はそれをテストすることはできません。しかし、私が知る限り、これは明示的に一時テーブルを持つパーサの問題です。同じだけの論理GO文

でコードを分割し、これを整理するために、通常のテーブル

で正常に動作します理想的に:あなたは一時テーブルを作成する前に、彼らが存在する場合、それらをドロップし、一時テーブルの存在をチェック、最後には、あなたも試してみて、使用することをお勧めします


GO、GOを発射、外出先で、その後、任意の後処理を発射、再び一時テーブルの作成を行い、外出先を発射最後に再びそれらをドロップすると、火災上記の場合は一時テーブルの代わりにテーブル変数を使用して解決しません

+0

はいありがとう。残念ながら、それはsprocのテーブルを作成しているので、同じバッチに入っていなければなりません(したがって、GOには行かない)。 –

0

あなたはいつも "ごまかす" ことができます:

DECLARE @SQL VARCHAR(200) 

IF (1=1) 
BEGIN 
    SET @SQL = 'CREATE TABLE #Temp  ' + 
       '(      ' + 
       ' a BIGINT NOT NULL, ' + 
       ' b BIGINT NOT NULL ' + 
       ')      ' 
END 
ELSE 
BEGIN 
    SET @SQL = 'CREATE TABLE #Temp  ' + 
       '(      ' + 
       ' a BIGINT NOT NULL, ' + 
       ' b BIGINT NOT NULL, ' + 
       ' c BIGINT NOT NULL ' + 
       ')      ' 
END 

EXEC SP_EXECUTESQL @SQL 
+0

これはすぐに有効範囲外になり、外側のスクリプトでは使用できないので機能しません。グローバルな一時テーブルである必要があります。または、一時テーブルのすべての用途が動的SQLにある必要があります。 –

2

代わりの#testを、完全修飾名を使用します。たとえば、

[tempdb].[dbo].[temptable] 

ここでこの小さなトリックを学んだInsert result of executing dynamic query into a table

Intellisenseは文句を言いますが、ストアドプロシージャを作成または変更することはできます。それを完了したら

、それをドロップするようにしてください:情報について

DROP TABLE [tempdb].[dbo].[temptable] 
関連する問題