2017-02-07 2 views
3

Я работаю над проектом, в котором мне нужна возможность получать и потреблять (т. Е. Извлекать информацию) из полученных JSON. Текущая версия SQL Server, которую я использую (и не буду меняться в течение следующих нескольких лет), - 2012, которая не включает поддержку этого (в отличие от версии 2016).Использование JSON в SQL Server 2012

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

Кто-нибудь есть или знает о рабочем решении?

Идея заключается в том, чтобы иметь что-то вроде:

Имея следующий JSON:

{ 
    "Obj1": { 
     "Obj1_S_1": [{ 
      "Obj1_S_1_S_1": "Blabla_1" 
     }, { 
      "Obj1_S_1_S_1": "Blabla_2" 
     }, { 
      "Obj1_S_1_S_1": "Blabla_3" 
     }, { 
      "Obj1_S_1_S_1": "Blabla_4" 
     }, { 
      "Obj1_S_1_S_1": "Blabla_5" 
     }, { 
      "Obj1_S_1_S_1": "Blabla_6" 
     }] 
    }, 
    "Obj2": "This is a simple string", 
    "Obj3": "456.33" 
} 

Я мог бы использовать следующий вызов:

SET @My_Param = GET_JSON(@Source_JSON, '*.Obj1.Obj1_S_1[3].Obj1_S_1_S_1') ; 

и я хотел бы получить значение 'Blabla_4' в переменная @My_Param.

Это тот же синтаксис, который используется в Oracle и MySQL.

Предложения, касающиеся конкретной потребности, будут высоко оценены.

+2

Это лучший ресурс, который я знаю для внедрения JSON до 2016: [Использование строк JSON в SQL Server - Фил Фактор] (https://www.simple-talk.com/sql/t-sql-programming/ consuming-json-strings-in-sql-server /), [Получение документов JSON из запросов SQL Server через TSQL - Фил-фактор] (https://www.simple-talk.com/sql/t-sql-programming/ (SQL Server JSON для таблицы и таблицы для JSON - Фил-фактор) (https://www.simple-talk.com/blogs/). sql-server-json-to-table-and-table-to-json /) – SqlZim

+0

Спасибо @SqlZim за ваше предложение. Я видел это предложение, но это не то, что я ищу (возможно, я не совсем понимаю его).Две основные причины: (1) Он просматривает весь JSON независимо от того, что вам действительно нужно (возможно, только первый элемент), и (2) он преобразует JSON в своего рода TABLE, и мой вопрос заключается в том, как результат будет когда JSON имеет, скажем, 6 разных уровней иерархии (например, массивы внутри массивов внутри массивов ....). – FDavidov

ответ

0

Может быть сделано с некоторыми стратегического разбора/сплит манипуляции

образца данных

Declare @S varchar(max) =' 
{ 
    "Obj1": { 
     "Obj1_S_1": [{ 
      "Obj1_S_1_S_1": "Blabla_1" 
     }, { 
      "Obj1_S_1_S_1": "Blabla_2" 
     }, { 
      "Obj1_S_1_S_1": "Blabla_3" 
     }, { 
      "Obj1_S_1_S_1": "Blabla_4" 
     }, { 
      "Obj1_S_1_S_1": "Blabla_5" 
     }, { 
      "Obj1_S_1_S_1": "Blabla_6" 
     }] 
    }, 
    "Obj2": "This is a simple string", 
    "Obj3": "456.33" 
} 
' 

Пример

--Clean-up JSON String and add '|||' as a standard delimeter 
Select @S = Replace(@S,MapFrm,MapTo) 
From (values ('"'  ,'') 
      ,(char(13),'|||') 
      ,(char(10),'|||') 
      ,('}'  ,'|||') 
      ,('{'  ,'|||') 
      ,('['  ,'|||') 
      ,(']'  ,'|||') 
     ) b (MapFrm,MapTo) 

Вариант с Анализировать/Split UDF

Select Item = left(RetVal,charindex(':',RetVal+':')-1) 
     ,Value = ltrim(right(RetVal,len(RetVal)-charindex(':',RetVal+':'))) 
From [dbo].[udf-Str-Parse](@S,'|||') 
Where Len(IsNull(RetVal,' '))>1 
Order By RetSeq 

Вариант без Анализировать/Split UDF

Select Item = left(RetVal,charindex(':',RetVal+':')-1) 
     ,Value = ltrim(right(RetVal,len(RetVal)-charindex(':',RetVal+':'))) 
From (
     Select RetSeq = Row_Number() over (Order By (Select null)) 
       ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)'))) 
     From (Select x = Cast('<x>' + replace((Select replace(@S,'|||','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
     Cross Apply x.nodes('x') AS B(i) 
     ) A 
Where Len(IsNull(RetVal,' '))>1 
Order By RetSeq 

возвращают

Item   Value 
Obj1  
Obj1_S_1  
Obj1_S_1_S_1 Blabla_1 
Obj1_S_1_S_1 Blabla_2 
Obj1_S_1_S_1 Blabla_3 
Obj1_S_1_S_1 Blabla_4 
Obj1_S_1_S_1 Blabla_5 
Obj1_S_1_S_1 Blabla_6 
Obj2   This is a simple string, 
Obj3   456.33 

ОДС, если это необходимо

CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(10)) 
Returns Table 
As 
Return ( 
    Select RetSeq = Row_Number() over (Order By (Select null)) 
      ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)'))) 
    From (Select x = Cast('<x>' + replace((Select replace(@String,@Delimiter,'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
    Cross Apply x.nodes('x') AS B(i) 
); 
--Thanks Shnugo for making this XML safe 
--Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',') 
--Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ') 
--Select * from [dbo].[udf-Str-Parse]('this,is,<test>,for,< & >',',') 
+0

Благодарим вас за ваш пост, но я вижу несколько проблем с ним: (1) вы предлагаете изменить как '' '' '' '' '' '' '' '' '' '' '' '' ', так и потерять различие между ** структурой ** и ** массивом ** (потенциально структур); (2) Представьте, что существует такая иерархия, что (например) 'Obj2' также является массивом, похожим на« Obj1 », и вам нужно ловить определенные элементы из каждого из обоих массивов. Любое решение ** должно ** уважать исходную структуру JSON, и я не вижу, как это делает ваше предложение. Может быть, я что-то упустил? – FDavidov