2011-07-25 118 views
32

我想输出SELECT语句的结果作为JSON对象。SQL Server SELECT到JSON函数

我想这是一个函数而不是一个存储过程!提前

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

感谢:

例如,下面的表用户

id name  active 
1  Bob Jones 1 
2  John Smith 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

而且......你到目前为止尝试过什么?这看起来更像* 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,name,active。另一次,它可能是身份证,姓名,电子邮件,日期等。 – jamesmhaley

+0

@sparkyfied:我不认为你可以帮助。如果您倾销到XML并且内容发生更改,您将会遇到同样的问题。 – Yuck

+0

@yuck,是否有可能在输出列名和值的列的循环中做到这一点(不想要代码片段,只是想知道它是否可能) – jamesmhaley

10

所以首先,我要感谢基里尔舒克的基本代码示例...谢谢!

我拿了那个,去建立一个程序来做我需要它做的事情,那就是给我一个基于“任何”结果集的JSON输出,我希望在SQL Server中的表对象(不可变) 。

理想情况下,我希望这是一个函数,但由于限制你可以在一个函数内做什么,该部分将不得不等待......也许是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

非常好!我知道你知道,但它不处理日期时间字段,但这没关系。这非常有用。 – smoore4

16

只是为了改善与最新的技术变革的答案。与SQL服务器2016

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

这与SQL Server 2014一起使用也 – matadur

+0

@matadur据我所知,FOR JSON支持只在2016年添加,是否有一些2014年更新允许它? – kerray

+0

也许它是在Management Studio的更新中添加的。我有Management Studio 12.0.2000.8的SQL Server 2014,FOR JSON有效。 – matadur