2011-07-25 13 views
32

SELECTステートメントの結果をJSONオブジェクトとして出力したいとします。JSON関数へのSQLサーバーの選択

私はこれをとしたいと思います。機能ではなく、ストアドプロシージャ!例えば

、下表のユーザー

id name  active 
1  Bob Jones 1 
2  John Smith 0 

は、次のように返されます:事前に

[{"id":1,"name":"Bob Jones","active":1},{"id":2,"name":"John Smith","active":0}] 

感謝を。

+2

これは、SQLクエリだけでは適切ではありません。あなたのデータベースの前に座っている何らかのプログラムでそれを行う方が理にかなっています。このデータを表示するためにどのようなプログラミング言語を使用していますか。 – schizodactyl

+0

http://www.adampresley.com/2010/07/experimenting-with-sql-to-json-in-sql.htmlには、CLR関数を使用してXMLレスポンスをJSONに解析する例があります。純粋なT-SQLで実行可能なソリューションが見つかるかどうかはわかりません。 – Yuck

+1

そして...あなたはこれまでに何を試しましたか?これは質問よりもa * bid *のように見えます... –

答えて

63

あなたはfor xml path、例えばを使用することができます。:

declare @t table(id int, name nvarchar(max), active bit) 
insert @t values (1, 'Bob Jones', 1), (2, 'John Smith', 0) 

select '[' + STUFF((
     select 
      ',{"id":' + cast(id as varchar(max)) 
      + ',"name":"' + name + '"' 
      + ',"active":' + cast(active as varchar(max)) 
      +'}' 

     from @t t1 
     for xml path(''), type 
    ).value('.', 'varchar(max)'), 1, 1, '') + ']' 

出力:

[{"id":1,"name":"Bob Jones","active":1},{"id":2,"name":"John Smith","active":0}] 
+0

私はあなたがここで何をしたのが好きです。しかし、テーブルの内容は変わる可能性があります。一度は、ID、名前、アクティブにすることができます。別の時間は、それは、ID、名前、電子メール、日付などがあります。 – jamesmhaley

+0

@ sparkyfied:私はあなたがそれを助けることができるとは思わない。 XMLにダンプしてコンテンツが変更されても、同じ問題が発生します。 – Yuck

+0

@yuck、列名と値を出力する列のループでこれを行うことは可能でしょうか(コード断片が必要ではなく、可能であるかどうかを知りたいだけです) – jamesmhaley

10

したがって、最初のオフ、私は基本的なコードサンプル用のキリルPolishchukに感謝したいと思います...ありがとうございました!

私はこれを取って、必要な処理を行うための手順を作成しました。これは、SQL Serverでテーブルオブジェクト(変数ではありません)を必要とする結果セットに基づいてJSON出力を与えることです。 。

理想的には、私は関数としてこれを望みますが、関数内でできることの制限のため、その部分は待たなければなりません。おそらくv2。 :)

はい、拡張プロシージャ(CLR)の登録は間違いなく簡単ですが、私はしばらくそのルートに行くことを避けたかったのです。

PS:ちょうどに入れて一時テーブル、 'tempdbの..#のテーブル名' の

ここにある:

  /* 
      Author:   Goran Biljetina 
      Create date: 03/13/2013 
      Description: consume a table object (not table var), output it as JSON Properties string 
      */ 

      /* 
      --> example run 
      -- EXEC dbo.JSONreturn @tblObjNameFQ='[database].[schema].[object_name_table]'; 
      */ 

      CREATE PROCEDURE dbo.JSONreturn 
      (
      @committedRead bit = 0 --> if 1 then committed else uncommitted read 
      ,@debugmode bit = 0 --> if 1 display certain outputs 
      ,@tblObjNameFQ varchar(128) --> fully qualified table object name, i.e. db.schema.object_name 
      ,@stringJSON nvarchar(max) = null OUTPUT 
      ) 

      AS 
      BEGIN 

       if @committedRead=0 
       begin 
        SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; --> evaluate if necessary in test phase 
       end 
        else if @committedRead=1 
         begin 
          SET TRANSACTION ISOLATION LEVEL READ COMMITTED; 
         end 

       SET NOCOUNT ON; 

       ---------------------------------------------------------------------------------------------------------- 
       if (PATINDEX('%[\.]%',@tblObjNameFQ)<1 AND patindex('%#%',@tblObjNameFQ)<1) OR LEN(@tblObjNameFQ)>(3*128) 
       begin 
        PRINT 'table (object) name not fully qualified or invalid!' 
        RETURN -1 
       end 


       declare 
       @objname varchar(128) 
       ,@dbname varchar(128) 
       ,@schema varchar(128) 
       ,@maxColNum int 
       ,@inc int 
       ,@dqsl_misc varchar(max) 
       ,@dsql_wrapper varchar(max) 
       ,@dsql_what varchar(max) 
       ,@dsql_where varchar(max) 
       ,@dsql_complete varchar(max) 


       create table #maxColNum (column_id int) 
       create table #ColPrep (colString varchar(max), column_id int) 
       create table #JSONoutput (string nvarchar(max)) 


       if patindex('%#%',@tblObjNameFQ)>0 
       begin 
        set @objname = (PARSENAME(@tblObjNameFQ,1)) 
        set @dbname = 'tempdb' 
       end 
       else if patindex('%#%',@tblObjNameFQ)<1 
        begin 
         set @dbname = SUBSTRING(@tblObjNameFQ,1,PATINDEX('%[\.]%',@tblObjNameFQ)-1) 
         set @objname = convert(varchar,(PARSENAME(@tblObjNameFQ,1))) 
         set @schema = convert(varchar,(PARSENAME(@tblObjNameFQ,2))) 
        end 

       --select @objname[@objname], @dbname[@dbname], @schema[@schema] 
       --select @dbname+'.'[email protected]+'.'[email protected] 

       set @dqsl_misc = 
       ' 
       select max(column_id) 
       from '[email protected]+'.sys.columns 
       where object_id = 
       (select object_id from '[email protected]+'.sys.objects where type = ''U'' and name like ''%'[email protected]+'%'') 
       ' 
       insert into #maxColNum 
       exec(@dqsl_misc) 

       set @maxColNum = (select column_id from #maxColNum) 
       set @dsql_what = '' 

       set @dsql_wrapper = 
       ' 
       select ''['' + STUFF((
         select 
          '',{''+<<REPLACE>> 
          +''}'' 
       ' 
       set @dsql_where = 
       ' 
         from '[email protected]+'.'+case when @schema is null then '' else @schema end+'.'[email protected]+' t1 
         for xml path(''''), type 
        ).value(''.'', ''varchar(max)''), 1, 1, '''') + '']'' 
       ' 

       set @dqsl_misc = 
       ' 
       select ''"''+sysc.name+''": '' 
         +case 
         when syst.name like ''%time%'' or syst.collationid is not null then ''"''''+cast(''+sysc.name+'' as varchar(max))+''''",'' 
         when syst.name = ''bit'' then ''''''+cast((case when ''+sysc.name+''=1 then ''''true'''' else ''''false'''' end) as varchar(max))+'''','' 
         else ''''''+cast(''+sysc.name+'' as varchar(max))+'''','' 
         end as colString, sysc.column_id 
       from '[email protected]+'.sys.columns sysc 
        join '[email protected]+'.sys.systypes syst 
         on sysc.system_type_id = syst.xtype and syst.xtype <> 240 and syst.name <> ''sysname'' 
       where object_id = (select object_id from '[email protected]+'.sys.objects where type = ''U'' and name like ''%'[email protected]+'%'') 
       order by sysc.column_id 
       ' 
       insert into #ColPrep 
       exec(@dqsl_misc) 

       set @inc = (select MIN(column_id) from #ColPrep) 


       while @inc<[email protected] 
       begin 

        set @dsql_what = @dsql_what+(select case 
               when @inc = @maxColNum then replace(colString,',','') 
               else colString end 
               from #ColPrep where column_id = @inc) 

        set @[email protected]+1 

        IF @inc>@maxColNum 
         set @dsql_what = ''''[email protected]_what+'''' 

        IF @inc>@maxColNum 
         BREAK 
        ELSE 
         CONTINUE 
       end 

       set @dsql_complete = REPLACE(@dsql_wrapper,'<<REPLACE>>',@dsql_what)[email protected]_where 

       insert into #JSONoutput 
       exec(@dsql_complete) 

       SET @stringJSON = (Select string from #JSONoutput) 
       ---------------------------------------------------------------------------------------------------------- 

      END 
+0

オハイオ州に追加するのを忘れてしまいました。いくつかのバグと矛盾があります...しかし、かなり速いですが、私はちょうど "私が知っている"と言うと思いました。 :) –

+0

非常に良い!あなたが知っていることは分かっていますが、datetimeフィールドは処理されませんが、それは問題ありません。これは非常に便利です。 – smoore4

16

ただ、最新の技術変化に答えを改善するため。 with SQL Server 2016

select id, name ,active 
    from tableName 
     FOR JSON AUTO 
+1

これはSQL Server 2014でも動作します – matadur

+0

@matadur私が見る限りでは、JSONサポートは2016年に追加されただけですが、2014年にはそれを許可する更新がいくつかありますか? – kerray

+0

Management Studioのアップデートで追加された可能性があります。私はManagement Studio 12.0.2000.8でSQL Server 2014を使用しており、FOR JSONが動作します。 – matadur