web-dev-qa-db-fra.com

SQL Server SELECT à la fonction JSON

Je voudrais sortir les résultats d'une instruction SELECT en tant qu'objet JSON.

Je voudrais que ce soit un Fonction et non un procédure stockée!

Par exemple, le tableau ci-dessous Utilisateurs

id    name        active
1     Bob Jones   1
2     John Smith  0

Serait retourné comme ceci:

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

Merci d'avance.

34
jamesmhaley

À partir de SQL Server 2016, vous pouvez utiliser 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

Avec les anciennes versions de SQL Server, vous pouvez utiliser for xml path, par exemple.:

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, '') + ']'

Production:

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

Juste pour améliorer la réponse avec les derniers changements technologiques. avec SQL Server 2016

select id, name ,active 
    from  tableName 
      FOR JSON AUTO
16
Amrik

Alors tout d'abord, je tiens à remercier Kirill Polishchuk pour l'exemple de code essentiel ... merci!

J'ai pris cela et suis allé créer une procédure pour faire ce dont j'ai besoin, c'est-à-dire me donner une sortie JSON basée sur "n'importe quel" jeu de résultats que je veux, c'est-à-dire un objet table (non variable) dans SQL Server.

Idéalement, je voudrais que ce soit une fonction, mais en raison des limitations de ce que vous pouvez faire dans une fonction, cette partie devra attendre ... peut-être v2. :)

Et oui, l'enregistrement d'une procédure étendue (CLR) sera certainement plus facile, mais je voulais éviter d'emprunter cette voie pour le moment.

PS: pour les tables temporaires, il suffit de mettre 'tempdb .. # tablename'

C'est ici:

            /* 
            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
10
Goran B.