0

一時テーブルを動的に作成する必要があるストアドプロシージャを作成しています。次のコードを試しましたが、テーブルが作成されませんでした。生成されたクエリをクエリウィンドウで実行すると、そこで正常に機能します。

--declare query variable
DECLARE @Query nvarchar(MAX)
SET @Query = 'CREATE TABLE #final (DATE int,'   


--DECLARE @COLUMNNAME VARIABLE
DECLARE @ColName nvarchar(10)

OPEN @taCur

FETCH NEXT FROM @taCur INTO @ColName
WHILE (@@FETCH_STATUS = 0)
BEGIN
    SET @Query = @Query + 'T_' + @ColName +' int,'   
    FETCH NEXT FROM @taCur INTO @ColName
END

SET @Query = @Query + 'TOTAL int,CUMM_TOTAL int)'
print @Query
EXEC sp_executesql @Query
--SET @Query = 'INSERT INTO #final (DATE) VALUES (1)'
SET @Query = 'SELECT * FROM #final'
print @Query
EXEC(@Query)

最終的に生成されたテーブルの作成クエリは次のとおりです

CREATE TABLE #final (DATE int,T_211E int,T_211G int,T_211H int,T_211J int,T_211L int,T_221F int,TOTAL int,CUMM_TOTAL int)
4

2 に答える 2

3

CREATEステートメントとSELECTステートメントで使用されるオブジェクト#finalは、同じスコープにありません。

クエリを構成する1つの方法は次のとおりです。

  • SQLステートメントをセミコロンで終了してみてください。必須ではありませんが、読みやすさのためにステートメントを区別するのに役立ちます。CREATEINSERT、およびSELECTステートメントの最後にセミコロンを含めていることに注意してください。

  • CREATEINSERT、およびSELECTが同じトランザクションで実行されていることがわかります。これにより、一時テーブルのスコープを失うことはありません。

スクリプト

    CREATE TABLE dbo.ColumnSchema
    (
        ColName NVARCHAR(10)
    );

    INSERT INTO dbo.ColumnSchema (ColName) VALUES
        ('211E'),
        ('211G'),
        ('211H'),
        ('211J'),
        ('211L'),
        ('211F');


DECLARE @Query      NVARCHAR(MAX);
DECLARE @ColName    NVARCHAR(10);

SET @Query = 'CREATE TABLE #final (DATE int,';

DECLARE taCursor CURSOR FOR 
    SELECT  ColName
    FROM    dbo.ColumnSchema;

OPEN taCursor

FETCH NEXT FROM taCursor 
    INTO @ColName

    WHILE (@@FETCH_STATUS = 0)
    BEGIN

        SET @Query = @Query + 'T_' + @ColName + ' int, '   

        FETCH NEXT FROM taCursor 
            INTO @ColName
    END

CLOSE       taCursor;
DEALLOCATE  taCursor;

SET @Query = @Query + 'TOTAL int,CUMM_TOTAL int); '
SET @Query = @Query + 'INSERT INTO #final (DATE) VALUES (1); '
SET @Query = @Query + 'SELECT * FROM #final; '

EXEC (@Query);

出力

DATE T_211E T_211G T_211H T_211J T_211L T_211F TOTAL CUMM_TOTAL
---- ------ ------ ------ ------ ------ ------ ----- ----------
1    NULL   NULL   NULL   NULL   NULL   NULL   NULL  NULL
于 2012-04-28T04:05:22.237 に答える
3

問題は、一時テーブルが作成されたスコープ内にのみ存在することです...これは最初のスコープ内にありますsp_executesql。ステートメントを呼び出すとselect、一時テーブルはスコープ内になくなります。

これを修正するには、一時テーブルで行う必要のあるすべてを含む単一の文字列を作成する必要があります。つまり、、、createおよびinsertすべてselectを1回のsp_executesql呼び出しで作成する必要があります。

ただし、コマンドの作成に使用されるすべての値を完全に制御できない場合、現在のアプローチはSQLインジェクションに対して脆弱である可能性があることに注意してください。

于 2012-04-28T04:02:20.357 に答える