2011-08-11 9 views
5

列名が動的に生成されるピボットテーブル要素にクエリを書き込みます。SQL Azureで一時テーブルを使用する

SET @query = N'SELECT STUDENT_ID, ROLL_NO, TITLE, STUDENT_NAME, EXAM_NAME, '+ 
      @cols + 
      ' INTO ##FINAL 
      FROM 
      (
       SELECT * 
       FROM #AVERAGES 
       UNION 
       SELECT * 
       FROM #MARKS 
       UNION 
       SELECT * 
       FROM #GRACEMARKS 
       UNION 
       SELECT * 
       FROM #TOTAL 
       ) p 
       PIVOT 
       (
       MAX([MARKS]) 
       FOR SUBJECT_ID IN 
       ('+ 
       @cols +') 
      ) AS FINAL 
      ORDER BY STUDENT_ID ASC, DISPLAYORDER ASC, EXAM_NAME ASC;' 

EXECUTE(@query) 

select * from ##FINAL 

このクエリはローカルデータベースで正しく機能しますが、SQL Azureではグローバルテンポラリテーブルが許可されていないため動作しません。

は今、私は私のローカルデータベースに#FINALから##FINA Lを変更した場合、それは

無効なオブジェクト名として私にエラーを与える「#FINAL」。

どうすればこの問題を解決できますか?

+0

SQLでうまくサポートされていないもの(可変数の列を持つ結果セット)を構築しようとしているので、特定の問題は解決しないと思います。一般的なケースでは、この作業をするためには、外側のスコープ(つまり、 'EXECUTE'の前)にtempテーブルを作成する必要がありますが、あなたが何カラムであるのか分からないときにはできません必要になる。 –

+0

実際、私はそれを試してみました。私はtempを作成して、@に入っているカラム名を入れました。私はin節でそれを使うことができなかったので、それはどんな目的にも役立たない。つまり、FOR SUBJECT_ID IN (SELECT cast(subject_id AS NVARCHAR)FROM #SUBJECT_ID_TABLE) –

+0

いいえ、ポイントは 'EXECUTE'の前に'#Final'テンポラリテーブルを作成することでした - これが両方のスコープでアクセスできる唯一の方法です。私は私の答えで働くかもしれない1つの方法を示しました。 –

答えて

10

さて、私はそれができないと言った後、私は方法があるかもしれません。しかし、それは醜いです。うまくいけば、あなたは以下のサンプルで遊ぶことができ、あなたのクエリにそれを適応させる(私はそれを書き込もうとするために、あなたのスキーマとデータがなくても、それはあまりにもトリッキーです):

declare @cols varchar(max) 
set @cols = 'object_id,schema_id,parent_object_id' 

--Create a temp table with the known columns 
create table #Boris (
    ID int IDENTITY(1,1) not null 
) 
--Alter the temp table to add the varying columns. Thankfully, they're all ints. 
--for unknown types, varchar(max) may be more appropriate, and will hopefully convert 
declare @tempcols varchar(max) 
set @tempcols = @cols 
while LEN(@tempcols) > 0 
begin 
    declare @col varchar(max) 
    set @col = CASE WHEN CHARINDEX(',',@tempcols) > 0 THEN SUBSTRING(@tempcols,1,CHARINDEX(',',@tempcols)-1) ELSE @tempcols END 
    set @tempcols = CASE WHEN LEN(@col) = LEN(@tempcols) THEN '' ELSE SUBSTRING(@tempcols,LEN(@col)+2,10000000) END 
    declare @sql1 varchar(max) 
    set @sql1 = 'alter table #Boris add [' + @col + '] int null' 
    exec (@sql1) 
end 

declare @sql varchar(max) 
set @sql = 'insert into #Boris (' + @cols + ') select ' + @cols + ' from sys.objects' 
exec (@sql) 

select * from #Boris 

drop table #Boris 

彼らキーは、一時テーブルを作成することです(スコープ内で実行中のコードEXEC)は、同じ一時表にアクセスできます。上記はSQL Server 2008上で動作しましたが、再生するAzureインスタンスはありませんので、そこではテストされていません。

+0

これを試してみましたが、適切な結果が得られる限り、ちょっと汚れているように見えますが、うまくいきます。ありがとうございます –

1

ダイナミックsqlでテーブルを作成すると、ダイナミックsqlで実行されたダイナミックsqlからテーブルが作成され、テーブルの外側には表示されません。

回避策があります。スタブテーブルを作成し、動的SQLで変更することができます。これは少しの文字列操作を必要としますが、このテクニックを使用してtsqlunitの動的データセットを生成しました。

CREATE TABLE #t1 
(
    DummyCol int 
) 

EXEC(N'ALTER TABLE #t1 ADD foo INT') 

EXEC ('insert into #t1(DummyCol, foo) 
VALUES(1,2)') 

EXEC ('ALTER TABLE #t1 DROP COLUMN DummyCol') 

select *from #t1 
+0

列はあらかじめわかっていませんか? –

+0

原則を実証するための概念実証コードです。列を派生させるには多くの方法がありますが、OPの場合、列は「@ cols」で知られています。 '@ cols'をalter文に変換するには、いくつかの操作が必要です。 Damien_The_Unbelieverはこのアプローチのより完全な例を書いています。 –

+0

申し訳ありません。あなたが正しいです。 –

関連する問題