web-dev-qa-db-ja.com

baseTypeのsql_variant_propertyをSQLServerのテーブル変数に復元するにはどうすればよいですか?

わかりました、タイトルが紛らわしいことは知っていますが、ここにあります。ところで、私はSQL Server2008を使用しています

ストレージコンテナとして使用しようとしているテーブルがあります。 3つの列があります。

reportID integer, 
dataLabel varchar(50),
dataValue sql_variant 

これを使用する方法は、reportIDを関数に渡し、正確に型指定されたテーブル変数を関数に返すことです。正確に入力されたパーツを除いて、プロセスがダウンしています。

以下は、一時テーブルを作成し、いくつかの値を挿入し、使用したいテーブル変数に値をピボットするスクリプトです。問題は、各列に返される値のタイプがsql_variantであり、それらをbaseTypeに変換する方法がわからないことです。 sql_variant_propertyを使用しようとしましたが(失敗しました)、理解できません。

たとえば、ファイナルテーブルでは、myDate列をsql_variantタイプではなくdateTimeタイプにします。

私を正しい方向に推し進めることができるSQLの達人はいますか?

create table #rStorage
    (
      reportID  bigint not null
    , dataLabel varchar (50) null
    , dataValue sql_variant null
    )
go

insert into #rStorage (reportID, datalabel, datavalue)
values (1, 'myInt', convert(int,5621))

insert into #rStorage (reportID, datalabel, datavalue)
values (1, 'mydate', convert(smalldatetime,getdate()))

insert into #rStorage (reportID, datalabel, datavalue)
values (1, 'myvarchar', convert(varchar(200),'testing Varchar'))

insert into #rStorage (reportID, datalabel, datavalue)
values (1, 'mydateNoTconverted', getDate())

select reportID
, dataLabel
, dataValue
into #tmp
from #rStorage

declare @QuestionList nvarchar(max)
, @qry nvarchar(max)

SELECT @QuestionList = STUFF(
 (SELECT ', ' + quotename(dataLabel)
 FROM #tmp
 GROUP BY dataLabel
 ORDER BY dataLabel
 FOR XML PATH(''))
 , 1, 2, '');

select @qry = '
 select *
 from #tmp

 pivot 
 (
 max(dataValue)
 for dataLabel in ('+@QuestionList+')
 ) as q
 '

print @qry

exec sp_executesql @qry;

drop table #tmp
drop table #rStorage

ストアドプロシージャはテーブル変数を返すことができないため、最終的な目標はudfです。だから私はカーソルといくつかの動的SQLでこれを試しました。私は近いと思いますが、以下の関数でエラーが発生します

関数と一部の拡張ストアドプロシージャのみを関数内から実行できます。重大度16状態2

コード:

if exists (select * from sysobjects where  name = N'fn_pivotReportStorage')
   drop function fn_pivotReportStorage
go

create function fn_pivotReportStorage 
 (@reportID bigint)
 returns @result table (reportID bigint)
as
begin

    declare @dataLabel sql_variant
    ,   @dataValue sql_variant
    ,   @dataType sql_variant

    ,   @alterTableStr nvarchar(max)

    declare thisCursor Cursor fast_forward for
       select   dataLabel
            ,   dataValue
            ,   dataType = case SQL_VARIANT_PROPERTY(dataValue,'BaseType') 
                        when 'varchar' then convert(varchar(50),SQL_VARIANT_PROPERTY(dataValue,'BaseType'))+'('+convert(varchar(50),SQL_VARIANT_PROPERTY(dataValue,'maxLength'))+')'
                        else SQL_VARIANT_PROPERTY(dataValue,'BaseType') end
        FROM reportStorage 
        where reportID = @reportID

    insert into @result (reportID) values (@reportID)

    open thisCursor

    fetch next from thisCursor into @dataLabel,@dataValue,@dataType 

    while @@fetch_status = 0
    begin
            select @alterTableStr = 'alter table @result add '+ convert(varchar(2000),@dataLabel)+' '+ convert(varchar(2000),@dataType) 
            exec sp_executesql @alterTableStr;
            select @alterTableStr = 'update @result set '+ convert(varchar(2000),@dataLabel)+' = '''  +convert(varchar(2000),@dataValue)+''''
            exec sp_executesql @alterTableStr;
     fetch next from thisCursor into @dataLabel,@dataValue,@dataType 
    end
    close thisCursor
    deallocate thisCursor

 return 
end
go
2
Lance

あなたが試みていることに多くの問題があり、この特定のアプローチがうまくいくとは思わない(目標は興味深いと思う):

returns @result table (reportID bigint)-これは基本的にスキーマにバインドされています。返されたテーブルのスキーマを変更することはできません。後で、この変数を「ALTER」しようとしますが、それは起こりません。

できたとしても、この部分:

select @alterTableStr = 'alter table @result add '+ convert(varchar(2000),@dataLabel)+' '+ convert(varchar(2000),@dataType) ;

exec sp_executesql @alterTableStr;

外側の部分の@resultに影響を与えることはありません-これらの動的SQL部分には独自のスコープがあり、この方法で呼び出し側の部分の変数にアクセスすることはできません

そして、それは本当にあなたが現在得ているエラーに帰着します-それはとにかく関数内で実行できないsp_executesqlです。

とにかく、少し進歩するのを助けるために、CSVとJSONデータの解析に関して接線方向に関連している(そして私は最近使用した)次の2つの記事を読むことをお勧めします。どちらも彼の階層のアイデア(ピボットされていない名前/値のもの)とリピボットを使用しており、そこでいくつかの便利なテクニックを見つけることができます。

http://www.simple-talk.com/sql/t-sql-programming/the-tsql-of-csv-comma-delimited-of-errors/

http://www.simple-talk.com/sql/t-sql-programming/sumption-json-strings-in-sql-server/

CLRを使用できる場合は、公開されたこの記事も役立つ可能性があります。

http://www.sqlservercentral.com/articles/.Net/94922/

4
Cade Roux