回答

收藏

改进SQL Server查询将任意表转换为JSON

技术问答 技术问答 158 人阅读 | 0 人回复 | 2023-09-14

经过大量的搜索和拼凑,使用了这些技术Web上的FOR$ V6 O/ K, `" Q9 C* f
XML和.nodes()命令转换结果集,创建合理的查询(而不是存储过程)SQL查询转换为JSON优秀的数组工作。
& A' ?9 o% f+ U3 T2 K查询将每个数据行编码为带有前导逗号的单个数据JSON对象。数据行用方括号,然后将整个结果集导出文件。
2 e. [, a& k! G3 T1 i我想看看外面是否有人能看到改善其性能的方法?
/ T* Y6 t: L- ~这是带示例表的查询:
0 d; n! O$ k' V7 C6 ~declare @xd table (col1 varchar(max),col2 int,col3 real,colNull int)insert into @xd select '',null,null,nullUNION ALL select 'ItemA',123,123.123,nullUNION ALL select 'ItemB',456,456.456,nullUNION ALL select '7890',789,789.789,nullselect{}UNION ALLselect ,{   STUFF(    (select      "'   r.value('local-name(.)','varchar(max) ":'          case when r.value('./@xsi:nil','varchar(max)') = 'true' then 'null          when isnumeric(r.value('.','varchar(max)')) = 1            then r.value('.','varchar(max)        else '"'   r.value('.','varchar(max) "          end    from rows.nodes('/row/*') as x(r) for xml path(''))    ),1,1,' }'from  -- Arbitrary query goes here,(fields go where t.* is,table where @xd t is)    select (select t.* for xml raw,type,elements XSINIL) rows    from @xd t) xdUNION ALLselect ']'我对此最大的批评是它运行缓慢。
4 J( [9 i* N! v; A$ |8 q. s目前完成4.2万行左右需要3:30。) f4 n# O" ]6 \
我的另一个批评是,它假设所有看起来像数字的东西都是数字。它不会试图找到最少的列类型(我不确定是否可以)。
0 p% b4 [* a! ~) X; @+ y最后的次要批评是,第一个数据银行将在前面添加逗号。从技术上讲,它不应该这样做。为了弥补这一点,它需要启动JSON在数组的第一行中使用空的JSON对象。  ?! v! ~6 c* }: A
当邀请其他评论(最好使用解决方案)时,我唯一真正的限制是解决方案可以在许多任何方面进行SQL重复查询,无需显式标识列名。
* _. R) Q8 J! B' g, i我正在使用SQL Server 2012。
/ `  V5 d' ~& Z( v% R2 p- r. O( v感谢其他像我这样的人,他们正在寻找广义SQL结果-> JSON请享受数组转换器!
& M" }# F, r- J! x3 b9 \/ \                                                               
7 y5 Z3 P: F3 a; u5 U    解决方案:                                                                ( o2 R% o& Y' M' }* f/ F
                                                                我说,如果您真的想提高性能,请使用元编程。下面的示例使用40,000行进行尝试,并在不到一秒的时间内返回结果(不算插入初始的40k好吧,在这个例子中只需要2秒左右)。它还考虑到你的数据类型,不要用引号引起数字。
# J( p9 N2 a1 o! Xdeclare @xd table (col1 varchar(max),col2 int,col3 real,colDate datetime,colNull int);declare @i int = 0;while @i < 10000 begin    set @i  = 1;    insert into @xd    select '',null,null,null,null    union all select 'ItemA',123,123.123,getDate(),null    union all select 'ItemB',456,456.456,getDate(),null    union all select '7890',789,789.789,getDate(),null;end;select *into #json_basefrom  -- Insert SQL Statement here    select * from @xd) t;declare @columns table  id int identity primary key,            name sysname,   datatype sysname,   is_number bit,   is_date bit);insert into @columns(name,datatype,is_number,is_date)select columns.name,types.name,      case when number_types.name is not NULL            then 1 else 0        end as is_number,      case when date_types.name is not NULL            then 1 else 0        end as is_datefrom tempdb.sys.columnsjoin tempdb.sys.types    on (columns.system_type_id = types.system_type_id)left join (values ('int'),('real'),('numeric         decimal'),('bigint'),('tinyint')) as number_types(name)    on (types.name = number_types.name)left join (values ('date'),('datetime'),('datetime2         smalldatetime'),('time'),('datetimeoffset')) as date_types(name)    on (types.name = date_types.name)where object_id = OBJECT_ID('tempdb..#json_base');declare @field_list varchar(max) = STUFF((    select QUOTENAME(QUOTENAME(name,'&quot;   ''''''''case when is_number =                       then 'COALESCE(LTRIM               QUOTENAME(name)  nullwhen is_date =                       then 'COALESCE(QUOTENAME(LTRIM(convert(varchar(max),                                        QUOTENAME(name)  &quot;nullelse 'COALESCE(QUOTENAME               QUOTENAME(name)   ',''&quot;null           end    from @columns    for xml path  1,5,');create table #json_result  id int identity primary key,   line varchar(max));declare @sql varchar(max) = REPLACE(   insert into #json_result  select{''''{f} ''}''  from #json_base','{f}',@field_list);exec(@sql);update #json_resultset line = STUFF(line,1,1,'')where id = 1;select '['UNION ALLselect linefrom #json_resultUNION ALLselect ']';drop table #json_base;drop table #json_result;
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则