2009-10-13 4 views

ответ

8
-- 
-- Author:  Thiago R. Santos           -- 
-- Create date: Aug 3rd 2008             -- 
-- Description: Returns the contents of a given table      -- 
--    in JavaScript Object Notation.        -- 
-- Params:                 -- 
--  @table_name: the table to execute the query      -- 
--  @registries_per_request: equivalent to "select top N * from table" 
-- 
--        replcing N by the actual number   
-- Influenced by Thomas Frank's post MySQL to JSON @ January 23, 2007  -- 
-- Post Url: http://www.thomasfrank.se/mysql_to_json.html     -- 



create procedure [dbo].[GetJSON] 
(
@table_name varchar(50), 
@registries_per_request smallint = null 
) 
as 
begin 
if((select count(*) from information_schema.tables where table_name = @table_name)  > 0) 
begin 
    declare @json varchar(max), 
      @line varchar(max), 
      @columns varchar(max), 
      @sql nvarchar(max), 
      @columnNavigator varchar(50), 
      @counter tinyint, 
      @size varchar(10) 

    if (@registries_per_request is null) 
    begin 
     set @size = '' 
    end 
    else 
    begin 
     set @size = 'top ' + convert(varchar, @registries_per_request) 
    end 
    set @columns = '{' 

    declare schemaCursor cursor 
    for select column_name from information_schema.columns where table_name = @table_name 
    open schemaCursor  

    fetch next from schemaCursor 
    into @columnNavigator 

    select @counter = count(*) from information_schema.columns where table_name = @table_name 

    while @@fetch_status = 0 
    begin 
     set @columns = @columns + '''''' + @columnNavigator + ''''':'''''' + convert(varchar, ' + @columnNavigator + ') + ''''''' 
     set @counter = @counter - 1 
     if(0 != @counter) 
     begin 
      set @columns = @columns + ',' 
     end 

     fetch next from schemaCursor 
     into @columnNavigator 
    end 

    set @columns = @columns + '}' 

    close  schemaCursor 
    deallocate schemaCursor 

    set @json = '[' 

    set @sql = 'select ' + @size + '''' + @columns + ''' as json into tmpJsonTable from ' + @table_name 
    exec sp_sqlexec @sql 

    select @counter = count(*) from tmpJsonTable 

    declare tmpCur cursor 
    for  select * from tmpJsonTable 
    open tmpCur 

    fetch next from tmpCur 
    into @line 

    while @@fetch_status = 0 
    begin 
     set @counter = @counter - 1 
     set @json = @json + @line 
     if (0 != @counter) 
     begin 
      set @json = @json + ',' 
     end 

     fetch next from tmpCur 
     into @line 
    end 

    set @json = @json + ']' 

    close  tmpCur 
    deallocate tmpCur 
    drop table tmpJsonTable 

    select @json as json 
end 
end 
+0

Хотелось поделиться этим удобным маленьким сценарием со всеми и с теми, у кого была такая же проблема, как у меня. Автор сценария цитируется. –

+0

Не хватает ли я там, где он должен избегать данных, чтобы он не разбивал JSON, если вы используете неправильный тип кавычки в строке? – Kev

+0

Ничего себе, это здорово !!! –

6

Я предполагаю, что это можно сделать, но это кажется чрезвычайно длинным и подверженным ошибкам способом достижения желаемого результата.

Если бы я был вами, я бы сломал проблему, чтобы взглянуть на технологию ORM вашего фрейма среднего уровня (ASP.NET, я предполагаю?), А затем снова сериализуется в JSON из фреймворка. Неудачная поддержка фреймворка (т. Е. Вы не в .NET 3+) Я бы еще предпочитал сериализацию базы данных в XML, а затем XSLT, преобразующий XML в JSON, так как XML значительно проще работать с сервером.

Название игры - это разделение проблем.

0

Ответ на jlech в порядке, но я не понимаю, почему вы не можете генерировать непосредственно метаданные VIEW, используя технику, аналогичную той, что описана в этом документе UNPIVOT answer, избегая КУРСОРА и таблицы темпа SELECT INTO.

0

Не сорвать вопрос OP, но мне интересно, является ли это в SQL лучшим/наиболее подходящим маршрутом? Мне кажется, что это может быть легче/эффективно сделано в коде.

Сначала мне было интересно узнать одно и то же (вот как я нашел это сообщение), но, пережевывая идею в течение нескольких минут, кажется, что это может быть лучше выполнено с использованием метода утилиты/расширения, который принимает набор данных & возвращает полученную строку JSON.

Конечно, у ОП могут быть веские причины для прохождения этого маршрута. Я просто думаю (набрав) вслух здесь ...

2

Ниже приведена полная переработка этой концепции. Если я что-то пропустил, добавьте примечание, и я отредактирую его, чтобы настроить.

-- 
-- Author:  Matthew D. Erwin (Snaptech, LLC) 
-- Create date: May 9, 2013             
-- Description: Returns the contents of a given table      
--    in JavaScript Object Notation JSON - 
-- 
--    Very notably useful for generating MOCK .json files 
--    for testing or before RESTful services are completed. 
-- 
--    This implementation: 
--     *removed cursor (using FOR XML PATH('')) 
--     *properly supports NULL vs quoted values 
--     *supports dates in ISO 8601 - presuming UTC 
--     *uses Data_Type and Is_Nullable info 
--     *escapes '\' 
--     *formats output with tabs/newlines 
--     *can return final results as XML to bypass 
--     truncation in SSMS 
--     *supports schema (e.g. [dbo].[TableName] 
--     *includes "recordCount" field 
-- Options:                 
--  @table_name: the table to execute the query       
--  @limit: equivalent to "select top N * from table" 
--  @ssms: flag to use if executing in Sql Server Management Studio 
--    to bypass result truncation limits. 
-- 
-- Inspired primarily by the 2008 work of Thiago R. Santos which was influenced by Thomas Frank. 
-- Usage: [dbo].[GetJSON] @Table_name = 'MySchema.MyTable', @limit = 50, @ssms = 0 

create procedure [dbo].[GetJSON] (
    @table_name varchar(max), 
    @limit int = null, 
    @ssms bit = 0 
) 
as 
begin 
     declare @json varchar(max), @query varchar(max), @table_schema varchar(max) = null 
if(charindex('.', @table_name) > 0) 
begin 
    set @table_schema = replace(replace(substring(@table_name, 0, charindex('.',@table_name)), '[', ''), ']', '') 
    set @table_name = replace(replace(substring(@table_name, charindex('.',@table_name) + 1,len(@table_name)), '[', ''), ']', '') 
end 

set @query = 
    'select ' + case when @limit is not null then 'top ' + cast(@limit as varchar(32)) + ' ' else '' end + '''{ '' + REVERSE(STUFF(REVERSE(''' + 
    CAST((SELECT ' "' + column_name + '" : ' + 
     case when is_nullable = 'YES' 
      then ''' + case when [' + column_name + '] is null then ''null'' else ' + 
       case when data_type like '%char%' or data_type like '%text%' then '''"'' + ' else '' end + 
       case when data_type like '%date%' then 'convert(varchar(23),[' + column_name + '], 126) + ''Z''' else 
       'replace(replace(replace(replace(cast([' + column_name + '] as varchar(max)),''\'',''\\''),''"'',''\"''),char(10),''\n''),char(13),''\n'') ' end + 
       case when data_type like '%char%' or data_type like '%text%' then '+ ''"''' else '' end + ' end + ''' 
      else 
       case when data_type like '%char%' or data_type like '%text%' then '"' else '' end + 
       ''' + ' + 
       case when data_type like '%date%' then 'convert(varchar(23),[' + column_name + '], 126) + ''Z' else 
       'replace(replace(replace(replace(cast([' + column_name + '] as varchar(max)),''\'',''\\''),''"'',''\"''),char(10),''\n''),char(13),''\n'') + ''' end + 
       case when data_type like '%char%' or data_type like '%text%' then '"' else '' end end + ',' AS [text()] 
       from information_schema.columns where table_name = @table_name and (@table_schema is null or table_schema = @table_schema) FOR XML PATH('')) as varchar(max)) + 
       '''),1,1,'''')) + '' }'' as json into tmpJsonTable from ' + @table_name + ' with(nolock) ' 
exec sp_sqlexec @query 

set @json = 
    '{' + char(10) + char(9) + 
    '"recordCount" : ' + Cast((select count(*) from tmpJsonTable) as varchar(32)) + ',' + char(10) + char(9) + 
    '"records" : ' + char(10) + char(9) + char(9) + '[' + char(10) 
    + REVERSE(STUFF(REVERSE(CAST((SELECT char(9) + char(9) + json + ',' + char(10) AS [text()] FROM tmpJsonTable FOR XML PATH('')) AS varchar(max))),1,2,'')) 
    + char(10) + char(9) + char(9) + ']' + char(10) + '}' 

drop table tmpJsonTable 
if(@ssms = 1 and len(@json) > 65535) --deal with Sql Server Management Studio text/grid truncation 
    select cast('<json><![CDATA[' + @json + ']]></json>' as xml) as jsonString 
else 
    select @json as jsonString 
end 
Смежные вопросы