SQL Server SELECT 到 JSON 函数

Posted

技术标签:

【中文标题】SQL Server SELECT 到 JSON 函数【英文标题】:SQL Server SELECT to JSON function 【发布时间】:2011-10-12 16:54:17 【问题描述】:

我想将SELECT 语句的结果输​​出为 JSON 对象。

我希望这是一个函数而不是存储过程

例如,下表用户

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]

提前致谢。

【问题讨论】:

这实际上并不适合仅使用 SQL 查询。使用位于数据库前面的某种程序来执行此操作更有意义。您使用什么编程语言来显示这些数据。 adampresley.com/2010/07/… 有一个使用 CLR 函数将 XML 响应解析为 JSON 的示例。我不知道你是否会在纯 T-SQL 中找到一个可行的解决方案。 还有...到目前为止,您尝试过什么?这看起来更像是一个出价而不是一个问题...... 我将 JSON 插入到表中,然后使用 JSON 输出。问题是,为什么我不构建 JSON 服务器端,它是否包含运行 storeprocedure 时创建的数据。 我试过weblogs.asp.net/thiagosantos/archive/2008/11/17/…。但它是一个存储过程,并没有工作 【参考方案1】:

从 SQL Server 2016 开始,您可以使用 for json:

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

select id, name, active
from @t
for json auto

对于旧版本的 SQL Server,您可以使用 for xml path,例如:

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]

【讨论】:

我喜欢你在这里所做的。但是表格的内容可能会改变。有一次它可能是 id、name、active。另一次可能是 id、姓名、电子邮件、日期等。 @sparkyfied:我认为你无能为力。如果您转储到 XML 并且内容发生更改,您将遇到同样的问题。 @yuck,是否可以在输出列名和值的列循环中执行此操作(不想要代码片段,只想知道是否可能) @sparkyfied:我确信这是可能的,但我看不出有什么优势。也许我错过了你的意图。 @Eitanmg,如果你使用for json,那么你不需要逃跑,如果你用for xml这种hacky方式,那么你需要逃跑【参考方案2】:

只是为了通过最新的技术变革来改进答案。使用 sql server 2016

select id, name ,active 
    from  tableName 
      FOR JSON AUTO

【讨论】:

@matadur 据我所知,FOR JSON 支持仅在 2016 年添加,2014 年是否有一些更新允许它? 可能是在 Management Studio 的更新中添加的。我有带有 Management Studio 12.0.2000.8 的 SQL Server 2014,并且 FOR JSON 有效。 我的错误——我测试的实际上是 SQL Server 2016;这只是 Mgmt Studio 2014。【参考方案3】:

首先,我要感谢 Kirill Polishchuk 提供的基本代码示例……谢谢!

我接受了它并构建了一个过程来做我需要它做的事情,那就是根据我想要的“任何”结果集给我一个 JSON 输出,即 SQL Server 中的表对象(不是变量)。

理想情况下,我希望将其作为一个函数,但是由于您可以在函数中执行的操作的限制,该部分将不得不等待......也许是 v2.2 版本。 :)

是的,注册扩展程序 (CLR) 肯定更容易,但我想暂时避免走这条路。

PS:对于临时表,只需输入 'tempdb..#tablename'

这里是:

            /* 
            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+'.'+@schema+'.'+@objname

                set @dqsl_misc =
                '
                select max(column_id) 
                from '+@dbname+'.sys.columns 
                where object_id = 
                (select object_id from '+@dbname+'.sys.objects where type = ''U'' and name like ''%'+@objname+'%'')
                '
                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 '+@dbname+'.'+case when @schema is null then '' else @schema end+'.'+@objname+' 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 '+@dbname+'.sys.columns sysc
                    join '+@dbname+'.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 '+@dbname+'.sys.objects where type = ''U'' and name like ''%'+@objname+'%'')
                order by sysc.column_id
                '
                insert into #ColPrep
                exec(@dqsl_misc)

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


                while @inc<=@maxColNum
                begin

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

                    set @inc=@inc+1

                    IF @inc>@maxColNum
                        set @dsql_what = ''''+@dsql_what+''''

                    IF @inc>@maxColNum
                        BREAK
                    ELSE
                        CONTINUE
                end

                set @dsql_complete = REPLACE(@dsql_wrapper,'<<REPLACE>>',@dsql_what)+@dsql_where

                insert into #JSONoutput
                exec(@dsql_complete)

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

            END

【讨论】:

哦,我忘记补充了,是的,我看到了一些错误和不一致的地方......但我很快就解决了这个问题,但我只是想我说,“是的,我知道”。 :) 非常好!我知道你知道,但它不处理日期时间字段,但没关系。这非常有用。

以上是关于SQL Server SELECT 到 JSON 函数的主要内容,如果未能解决你的问题,请参考以下文章

使用php将sql server数据转换为json

MS SQL Server 查询后返回 JSON

使用 JSON_VALUE 访问 SQL Server 2016 中的 JSON 数组

C#Dapper使用JSON_VALUE进行SQL Server 2016

SQL Server SELECT 到现有表

如何使用 Sql Server 2008 获取用于插入到 select 中的 scope_identity 列表?