TSQL에서 JSON 구문 분석


115

그것은 구문 분석 할 수 있는가 JSONTSQL?

JSON문자열 을 만들려는 것이 아닙니다 . 오히려, 나는 구문 분석 할 JSON로 전달 된 문자열을 parameter.

답변:


61

업데이트 : SQL Server 2016부터 TSQL에서 JSON 구문 분석이 가능합니다 .

기본적으로 지원이 없습니다. CLR을 사용해야합니다. 엄청난 마조히즘적인 행진이 있고 SQL로 JSON 파서를 작성하고 싶지 않다면 그렇게 간단합니다.

일반적으로 사람들은 DB에서 JSON 출력을 요청하고 인터넷에 예제가 있습니다. 하지만 DB에?


60
JSON은 매우 간단한 프로토콜이므로 엄청난 양의 마조히즘이 필요하지 않습니다. 일단 가지고 있으면 모든 JSON에 대해 하나의 루틴을 사용할 수 있습니다. 어쨌든, 내가 여기 당신을 위해 그것을 한 적이 simple-talk.com/sql/t-sql-programming/...
필 팩터

10
필 팩터 : 나는 수년 동안 당신의 기사를 읽고 있습니다. 오늘 이 기사를 쓰지 않았다면 아마도 6 개월 전에 내가 대답했을 때 인용했을 것입니다.
gbn

9
가 내장되어 지원 새 SQL Server 2016에서 JSON 텍스트를 구문 분석
조반 MSFT에게

다음은 JSon 문자열을 가져 와서 쿼리 할 수있는 테이블과 열로 출력하는 방법을 설명하는 Simple Talk 웹 사이트의 매우 유용한 기사입니다. 이것은 SQL Server 2016 용입니다. https://www.simple-talk.com/sql/learn-sql-server/json-support-in-sql-server-2016/
codeaf

다음은 CLR appoach를 사용하여 JSON을 구문 분석하는 방법에 대한 코드 예제입니다. blog.dotnetframework.org/2016/12/06/…
Fiach Reid

238

JSON 파서를 작성했다는 점에서 엄청난 마조히즘적인 행진을 보이는 것 같습니다. JSON 문서를 데이터 테이블을 업데이트하는 데 사용하기 쉬운 SQL 인접성 목록 테이블로 변환합니다. 사실, 나는 역방향 프로세스를 수행하는 코드를 작성했다는 점에서 더 나빴습니다. 계층 구조 테이블에서 JSON 문자열로 이동하는 것입니다.

기사 및 코드는 다음과 같습니다. Consuming Json strings in SQL server .

Select * from parseJSON('{
  "Person":
  {
     "firstName": "John",
     "lastName": "Smith",
     "age": 25,
     "Address":
     {
        "streetAddress":"21 2nd Street",
        "city":"New York",
        "state":"NY",
        "postalCode":"10021"
     },
     "PhoneNumbers":
     {
        "home":"212 555-1234",
        "fax":"646 555-4567"
     }
  }
}
')

얻으려면 :

여기에 이미지 설명 입력


이것은 훌륭한 기능이지만 음수에서 "-"를 제거하는 등 몇 가지 제한 사항이 있습니다.
Gavin

아주 멋지다! 스크립트에 오타가 하나 있습니다. IF OBJECT_ID (N'dbo.parseJSON ') IS NOT NULL DROP FUNCTION dbo.JSONEscaped GO-IF 테스트에서 dbo.JSONEscaped를 테스트해야합니다.
isapir 2013

@phil dbo.parseJSON은 대용량 데이터의 경우 매우 느리게 작동합니다. 그 안에 다른 방법을 사용하여 그 시간을 줄일 수 있습니까?
크래커

궁금합니다. SQL Server 2016에 새로 추가 된 네이티브 JSON 지원에 대해 어떻게 생각하십니까?
무료 컨설팅

이것은 대단하지만 음수에서 "-"를 제거하지 않는 방법이 있습니까? 나는 확실히 알아낼 경우 수 없거나 그 ... 왜 일어나는지
Nikoline Hejbøl

26

마지막으로 SQL Server 2016은 네이티브 JSON 지원을 추가합니다 !!

참고 :

SQL Server 2016의 추가 기능은 다음과 같습니다.

  • 행 수준 보안 및 동적 데이터 마스킹에 대한 추가 보안 향상으로 Always
    Encrypted로 보안 투자를 마무리합니다 .
  • 다중 동기 복제본 및 보조 부하
    분산 을 통해보다 강력한 가용성과 재해 복구를 위해 AlwaysOn이 개선되었습니다 .
  • 더 나은 성능을 제공하고 다양한 유형의 데이터를 지원하는 네이티브 JSON 지원.
  • SQL Server EIM (Enterprise Information Management) 도구 및 Analysis Services는 성능, 유용성 및 확장 성을 업그레이드합니다.
  • 더 빠른 하이브리드 백업, 고 가용성 및 재해 복구 시나리오를 통해 온-프레미스 데이터베이스를 Azure에 백업 및 복원
    하고 SQL Server AlwaysOn 보조 데이터베이스를 Azure 에 배치합니다.

발표 : http://blogs.technet.com/b/dataplatforminsider/archive/2015/05/04/sql-server-2016-public-preview-coming-this-summer.aspx

기능 블로그 게시물 : http://blogs.msdn.com/b/jocapc/archive/2015/05/16/json-support-in-sql-server-2016.aspx


2
아마도 SQL Server 2016 CTP 3은 OpenJSON 구문을 사용하여 JSON에서 SQL Server로 지원할 것입니다. kodyaz.com/t-sql/sql-server-2016-openjson-error.aspx
Eralper

7

SQL 서버 2016 명을 지원 json data하여 구문 분석 OPENJSON. 행과 열에 OPENJSON매핑하는 json data데 사용할 수 있습니다 .

너의 json Data

[
 { "id" : 2,"name": "John"},
 { "id" : 5,"name": "John"}
]

다음은 SQL에서 json을 처리하는 방법입니다.

//@pJson is json data passed from code.  

INSERT INTO YourTable (id, Name)
 SELECT id, name
 FROM OPENJSON(@pJson)
 WITH (id int,
       name nvarchar(max))

다음 은이 주제를 다루는 자세한 기사입니다.


5

얼마 전에 SQL Server 2016+ JSON 파서를 개발했습니다. 나는 모든 프로젝트에서 이것을 사용합니다-아주 좋은 성능입니다. 다른 사람에게도 도움이되기를 바랍니다.

기능의 전체 코드 :

ALTER FUNCTION [dbo].[SmartParseJSON] (@json NVARCHAR(MAX))
RETURNS @Parsed TABLE (Parent NVARCHAR(MAX),Path NVARCHAR(MAX),Level INT,Param NVARCHAR(4000),Type NVARCHAR(255),Value NVARCHAR(MAX),GenericPath NVARCHAR(MAX))
AS
BEGIN
    -- Author: Vitaly Borisov
    -- Create date: 2018-03-23
    ;WITH crData AS (
        SELECT CAST(NULL AS NVARCHAR(4000)) COLLATE DATABASE_DEFAULT AS [Parent]
            ,j.[Key] AS [Param],j.Value,j.Type
            ,j.[Key] AS [Path],0 AS [Level]
            ,j.[Key] AS [GenericPath]
        FROM OPENJSON(@json) j
        UNION ALL
        SELECT CAST(d.Path AS NVARCHAR(4000)) COLLATE DATABASE_DEFAULT AS [Parent]
            ,j.[Key] AS [Param],j.Value,j.Type 
            ,d.Path + CASE d.Type WHEN 5 THEN '.' WHEN 4 THEN '[' ELSE '' END + j.[Key] + CASE d.Type WHEN 4 THEN ']' ELSE '' END AS [Path]
            ,d.Level+1
            ,d.GenericPath + CASE d.Type WHEN 5 THEN '.' + j.[Key] ELSE '' END AS [GenericPath]
        FROM crData d 
        CROSS APPLY OPENJSON(d.Value) j
        WHERE ISJSON(d.Value) = 1
    )
    INSERT INTO @Parsed(Parent, Path, Level, Param, Type, Value, GenericPath)
    SELECT d.Parent,d.Path,d.Level,d.Param
        ,CASE d.Type 
            WHEN 1 THEN CASE WHEN TRY_CONVERT(UNIQUEIDENTIFIER,d.Value) IS NOT NULL THEN 'UNIQUEIDENTIFIER' ELSE 'NVARCHAR(MAX)' END 
            WHEN 2 THEN 'INT' 
            WHEN 3 THEN 'BIT' 
            WHEN 4 THEN 'Array' 
            WHEN 5 THEN 'Object' 
                ELSE 'NVARCHAR(MAX)'
         END AS [Type]
        ,CASE 
            WHEN d.Type = 3 AND d.Value = 'true' THEN '1'
            WHEN d.Type = 3 AND d.Value = 'false' THEN '0'
                ELSE d.Value
         END AS [Value]
        ,d.GenericPath
    FROM crData d
    OPTION(MAXRECURSION 1000) /*Limit to 1000 levels deep*/
    ;
    RETURN;
END
GO

사용 예 :

DECLARE @json NVARCHAR(MAX) = '{"Objects":[{"SomeKeyID":1,"Value":3}],"SomeParam":"Lalala"}';
SELECT j.Parent, j.Path, j.Level, j.Param, j.Type, j.Value, j.GenericPath 
FROM dbo.SmartParseJSON(@json) j;

다단계 사용의 예 :

DECLARE @json NVARCHAR(MAX) = '{"Objects":[{"SomeKeyID":1,"Value":3}],"SomeParam":"Lalala"}';
DROP TABLE IF EXISTS #ParsedData;
SELECT j.Parent, j.Path, j.Level, j.Param, j.Type, j.Value, j.GenericPath 
INTO #ParsedData
FROM dbo.SmartParseJSON(@json) j;

SELECT COALESCE(p2.GenericPath,p.GenericPath) AS [GenericPath]
    ,COALESCE(p2.Param,p.Param) AS [Param]
    ,COALESCE(p2.Value,p.Value) AS [Value]
FROM #ParsedData p
LEFT JOIN #ParsedData p1 ON p1.Parent = p.Path AND p1.Level = 1
LEFT JOIN #ParsedData p2 ON p2.Parent = p1.Path AND p2.Level = 2
WHERE p.Level = 0
;
DROP TABLE IF EXISTS #ParsedData;

1
공유해 주셔서 감사합니다.
André Voltolini

4

나는 또 다른 JSON 파서를 작성했기 때문에 거대한 마조히즘 적 행진을 가지고 있습니다. 이것은 절차 적 접근 방식을 사용합니다. similat SQL 계층 목록 테이블을 사용하여 구문 분석 된 데이터를 저장합니다. 또한 패키지에는 다음이 포함됩니다.

  • 리버스 프로세스 : 계층 구조에서 JSON으로
  • 쿼리 함수 : JSON 개체에서 특정 값 가져 오기

자유롭게 사용하고 재미있게 즐기십시오.

http://www.codeproject.com/Articles/1000953/JSON-for-Sql-Server-Part


+1 감사는 PhilFactor 버전보다 훌륭하게 작동합니다. 나는 SQL 서버 2008하지만 (어떤을 위해 약간 바보로 내려했다 iif함수 나 OFFSET)
vanderwyst


0
CREATE FUNCTION dbo.parseJSON( @JSON NVARCHAR(MAX))
RETURNS @hierarchy TABLE
  (
   element_id INT IDENTITY(1, 1) NOT NULL, /* internal surrogate primary key gives the order of parsing and the list order */
   sequenceNo [int] NULL, /* the place in the sequence for the element */
   parent_ID INT,/* if the element has a parent then it is in this column. The document is the ultimate parent, so you can get the structure from recursing from the document */
   Object_ID INT,/* each list or object has an object id. This ties all elements to a parent. Lists are treated as objects here */
   NAME NVARCHAR(2000),/* the name of the object */
   StringValue NVARCHAR(MAX) NOT NULL,/*the string representation of the value of the element. */
   ValueType VARCHAR(10) NOT null /* the declared type of the value represented as a string in StringValue*/
  )
AS
BEGIN
  DECLARE
    @FirstObject INT, --the index of the first open bracket found in the JSON string
    @OpenDelimiter INT,--the index of the next open bracket found in the JSON string
    @NextOpenDelimiter INT,--the index of subsequent open bracket found in the JSON string
    @NextCloseDelimiter INT,--the index of subsequent close bracket found in the JSON string
    @Type NVARCHAR(10),--whether it denotes an object or an array
    @NextCloseDelimiterChar CHAR(1),--either a '}' or a ']'
    @Contents NVARCHAR(MAX), --the unparsed contents of the bracketed expression
    @Start INT, --index of the start of the token that you are parsing
    @end INT,--index of the end of the token that you are parsing
    @param INT,--the parameter at the end of the next Object/Array token
    @EndOfName INT,--the index of the start of the parameter at end of Object/Array token
    @token NVARCHAR(200),--either a string or object
    @value NVARCHAR(MAX), -- the value as a string
    @SequenceNo int, -- the sequence number within a list
    @name NVARCHAR(200), --the name as a string
    @parent_ID INT,--the next parent ID to allocate
    @lenJSON INT,--the current length of the JSON String
    @characters NCHAR(36),--used to convert hex to decimal
    @result BIGINT,--the value of the hex symbol being parsed
    @index SMALLINT,--used for parsing the hex value
    @Escape INT --the index of the next escape character


  DECLARE @Strings TABLE /* in this temporary table we keep all strings, even the names of the elements, since they are 'escaped' in a different way, and may contain, unescaped, brackets denoting objects or lists. These are replaced in the JSON string by tokens representing the string */
    (
     String_ID INT IDENTITY(1, 1),
     StringValue NVARCHAR(MAX)
    )
  SELECT--initialise the characters to convert hex to ascii
    @characters='0123456789abcdefghijklmnopqrstuvwxyz',
    @SequenceNo=0, --set the sequence no. to something sensible.
  /* firstly we process all strings. This is done because [{} and ] aren't escaped in strings, which complicates an iterative parse. */
    @parent_ID=0;
  WHILE 1=1 --forever until there is nothing more to do
    BEGIN
      SELECT
        @start=PATINDEX('%[^a-zA-Z]["]%', @json collate SQL_Latin1_General_CP850_Bin);--next delimited string
      IF @start=0 BREAK --no more so drop through the WHILE loop
      IF SUBSTRING(@json, @start+1, 1)='"'
        BEGIN --Delimited Name
          SET @start=@Start+1;
          SET @end=PATINDEX('%[^\]["]%', RIGHT(@json, LEN(@json+'|')-@start) collate SQL_Latin1_General_CP850_Bin);
        END
      IF @end=0 --no end delimiter to last string
        BREAK --no more
      SELECT @token=SUBSTRING(@json, @start+1, @end-1)
      --now put in the escaped control characters
      SELECT @token=REPLACE(@token, FROMString, TOString)
      FROM
        (SELECT
          '\"' AS FromString, '"' AS ToString
         UNION ALL SELECT '\\', '\'
         UNION ALL SELECT '\/', '/'
         UNION ALL SELECT '\b', CHAR(08)
         UNION ALL SELECT '\f', CHAR(12)
         UNION ALL SELECT '\n', CHAR(10)
         UNION ALL SELECT '\r', CHAR(13)
         UNION ALL SELECT '\t', CHAR(09)
        ) substitutions
      SELECT @result=0, @escape=1
  --Begin to take out any hex escape codes
      WHILE @escape>0
        BEGIN
          SELECT @index=0,
          --find the next hex escape sequence
          @escape=PATINDEX('%\x[0-9a-f][0-9a-f][0-9a-f][0-9a-f]%', @token collate SQL_Latin1_General_CP850_Bin)
          IF @escape>0 --if there is one
            BEGIN
              WHILE @index<4 --there are always four digits to a \x sequence  
                BEGIN
                  SELECT --determine its value
                    @result=@result+POWER(16, @index)
                    *(CHARINDEX(SUBSTRING(@token, @escape+2+3-@index, 1),
                                @characters)-1), @index=@index+1 ;

                END
                -- and replace the hex sequence by its unicode value
              SELECT @token=STUFF(@token, @escape, 6, NCHAR(@result))
            END
        END
      --now store the string away
      INSERT INTO @Strings (StringValue) SELECT @token
      -- and replace the string with a token
      SELECT @JSON=STUFF(@json, @start, @end+1,
                    '@string'+CONVERT(NVARCHAR(5), @@identity))
    END
  -- all strings are now removed. Now we find the first leaf. 
  WHILE 1=1  --forever until there is nothing more to do
  BEGIN

  SELECT @parent_ID=@parent_ID+1
  --find the first object or list by looking for the open bracket
  SELECT @FirstObject=PATINDEX('%[{[[]%', @json collate SQL_Latin1_General_CP850_Bin)--object or array
  IF @FirstObject = 0 BREAK
  IF (SUBSTRING(@json, @FirstObject, 1)='{')
    SELECT @NextCloseDelimiterChar='}', @type='object'
  ELSE
    SELECT @NextCloseDelimiterChar=']', @type='array'
  SELECT @OpenDelimiter=@firstObject

  WHILE 1=1 --find the innermost object or list...
    BEGIN
      SELECT
        @lenJSON=LEN(@JSON+'|')-1
  --find the matching close-delimiter proceeding after the open-delimiter
      SELECT
        @NextCloseDelimiter=CHARINDEX(@NextCloseDelimiterChar, @json,
                                      @OpenDelimiter+1)
  --is there an intervening open-delimiter of either type
      SELECT @NextOpenDelimiter=PATINDEX('%[{[[]%',
             RIGHT(@json, @lenJSON-@OpenDelimiter)collate SQL_Latin1_General_CP850_Bin)--object
      IF @NextOpenDelimiter=0
        BREAK
      SELECT @NextOpenDelimiter=@NextOpenDelimiter+@OpenDelimiter
      IF @NextCloseDelimiter<@NextOpenDelimiter
        BREAK
      IF SUBSTRING(@json, @NextOpenDelimiter, 1)='{'
        SELECT @NextCloseDelimiterChar='}', @type='object'
      ELSE
        SELECT @NextCloseDelimiterChar=']', @type='array'
      SELECT @OpenDelimiter=@NextOpenDelimiter
    END
  ---and parse out the list or name/value pairs
  SELECT
    @contents=SUBSTRING(@json, @OpenDelimiter+1,
                        @NextCloseDelimiter-@OpenDelimiter-1)
  SELECT
    @JSON=STUFF(@json, @OpenDelimiter,
                @NextCloseDelimiter-@OpenDelimiter+1,
                '@'+@type+CONVERT(NVARCHAR(5), @parent_ID))
  WHILE (PATINDEX('%[A-Za-z0-9@+.e]%', @contents collate SQL_Latin1_General_CP850_Bin))<>0
    BEGIN
      IF @Type='Object' --it will be a 0-n list containing a string followed by a string, number,boolean, or null
        BEGIN
          SELECT
            @SequenceNo=0,@end=CHARINDEX(':', ' '+@contents)--if there is anything, it will be a string-based name.
          SELECT  @start=PATINDEX('%[^A-Za-z@][@]%', ' '+@contents collate SQL_Latin1_General_CP850_Bin)--AAAAAAAA
          SELECT @token=SUBSTRING(' '+@contents, @start+1, @End-@Start-1),
            @endofname=PATINDEX('%[0-9]%', @token collate SQL_Latin1_General_CP850_Bin),
            @param=RIGHT(@token, LEN(@token)-@endofname+1)
          SELECT
            @token=LEFT(@token, @endofname-1),
            @Contents=RIGHT(' '+@contents, LEN(' '+@contents+'|')-@end-1)
          SELECT  @name=stringvalue FROM @strings
            WHERE string_id=@param --fetch the name
        END
      ELSE
        SELECT @Name=null,@SequenceNo=@SequenceNo+1
      SELECT
        @end=CHARINDEX(',', @contents)-- a string-token, object-token, list-token, number,boolean, or null
      IF @end=0
        SELECT  @end=PATINDEX('%[A-Za-z0-9@+.e][^A-Za-z0-9@+.e]%', @Contents+' ' collate SQL_Latin1_General_CP850_Bin)
          +1
       SELECT
        @start=PATINDEX('%[^A-Za-z0-9@+.e][A-Za-z0-9@+.e]%', ' '+@contents collate SQL_Latin1_General_CP850_Bin)
      --select @start,@end, LEN(@contents+'|'), @contents 
      SELECT
        @Value=RTRIM(SUBSTRING(@contents, @start, @End-@Start)),
        @Contents=RIGHT(@contents+' ', LEN(@contents+'|')-@end)
      IF SUBSTRING(@value, 1, 7)='@object'
        INSERT INTO @hierarchy
          (NAME, SequenceNo, parent_ID, StringValue, Object_ID, ValueType)
          SELECT @name, @SequenceNo, @parent_ID, SUBSTRING(@value, 8, 5),
            SUBSTRING(@value, 8, 5), 'object'
      ELSE
        IF SUBSTRING(@value, 1, 6)='@array'
          INSERT INTO @hierarchy
            (NAME, SequenceNo, parent_ID, StringValue, Object_ID, ValueType)
            SELECT @name, @SequenceNo, @parent_ID, SUBSTRING(@value, 7, 5),
              SUBSTRING(@value, 7, 5), 'array'
        ELSE
          IF SUBSTRING(@value, 1, 7)='@string'
            INSERT INTO @hierarchy
              (NAME, SequenceNo, parent_ID, StringValue, ValueType)
              SELECT @name, @SequenceNo, @parent_ID, stringvalue, 'string'
              FROM @strings
              WHERE string_id=SUBSTRING(@value, 8, 5)
          ELSE
            IF @value IN ('true', 'false')
              INSERT INTO @hierarchy
                (NAME, SequenceNo, parent_ID, StringValue, ValueType)
                SELECT @name, @SequenceNo, @parent_ID, @value, 'boolean'
            ELSE
              IF @value='null'
                INSERT INTO @hierarchy
                  (NAME, SequenceNo, parent_ID, StringValue, ValueType)
                  SELECT @name, @SequenceNo, @parent_ID, @value, 'null'
              ELSE
                IF PATINDEX('%[^0-9]%', @value collate SQL_Latin1_General_CP850_Bin)>0
                  INSERT INTO @hierarchy
                    (NAME, SequenceNo, parent_ID, StringValue, ValueType)
                    SELECT @name, @SequenceNo, @parent_ID, @value, 'real'
                ELSE
                  INSERT INTO @hierarchy
                    (NAME, SequenceNo, parent_ID, StringValue, ValueType)
                    SELECT @name, @SequenceNo, @parent_ID, @value, 'int'
      if @Contents=' ' Select @SequenceNo=0
    END
  END
INSERT INTO @hierarchy (NAME, SequenceNo, parent_ID, StringValue, Object_ID, ValueType)
  SELECT '-',1, NULL, '', @parent_id-1, @type
--
   RETURN
END
GO

--- JSON 구문

Declare @pars varchar(MAX) = 
' {"shapes":[{"type":"polygon","geofenceName":"","geofenceDescription":"",
"geofenceCategory":"1","color":"#1E90FF","paths":[{"path":[{
"lat":"26.096254906968525","lon":"65.709228515625"}
,{"lat":"28.38173504322308","lon":"66.741943359375"}
,{"lat":"26.765230565697482","lon":"68.983154296875"}
,{"lat":"26.254009699865737","lon":"68.609619140625"}
,{"lat":"25.997549919572112","lon":"68.104248046875"}
,{"lat":"26.843677401113002","lon":"67.115478515625"}
,{"lat":"25.363882272740255","lon":"65.819091796875"}]}]}]}'
Select * from parseJSON(@pars) AS MyResult 

3
-1 설명이나 링크없이 다른 사람의 답변을 복사하여 붙여 넣는 경우. 이 솔루션은 2010 년 11 월에 작성된 RedGate에서 제공됩니다. red-gate.com/simple-talk/sql/t-sql-programming/… SQL Server 2016 이상을 실행하는 사용자는 SQL Server가 기본 솔루션을 도입 했으므로이 솔루션을 사용하지 마십시오.
MGot90


-4

나는 이것에 대한 꽤 깔끔한 기사를 보았다 ... 그래서 당신이 이것을 좋아한다면 :

CREATE PROC [dbo].[spUpdateMarks]
    @inputJSON VARCHAR(MAX)  -- '[{"ID":"1","C":"60","CPP":"60","CS":"60"}]'
AS
BEGIN
    -- Temp table to hold the parsed data
    DECLARE @TempTableVariable TABLE(
        element_id INT,
        sequenceNo INT,
        parent_ID INT,
        [Object_ID] INT,
        [NAME] NVARCHAR(2000),
        StringValue NVARCHAR(MAX),
        ValueType NVARCHAR(10)
    )
    -- Parse JSON string into a temp table
    INSERT INTO @TempTableVariable
    SELECT * FROM parseJSON(@inputJSON)
END

여기를보십시오 :

https://www.simple-talk.com/sql/t-sql-programming/consuming-json-strings-in-sql-server/

여기에 대한 완전한 ASP.Net 프로젝트가 있습니다. http://www.codeproject.com/Articles/788208/Update-Multiple-Rows-of-GridView-using-JSON-in-ASP


10
이미 기사의 원저자의 답변이 있습니다 : stackoverflow.com/a/4187412/389424
janv8000
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.