Results 1 to 7 of 7

Thread: Parsing nested json in sql server

  1. #1

    Thread Starter
    Frenzied Member usamaalam's Avatar
    Join Date
    Nov 2002
    Location
    Karachi
    Posts
    1,308

    Parsing nested json in sql server

    Hello Everybody,

    I have the following json where there can be multiple vehicles and each vehicle can contain multiple trips. I need to insert vehicles in to the TVHC table and for each vehicle insert trips into TTRP table.

    Code:
    [
      {
        "VHC_VTY_CDE": "CAR", 
        "VHC_NAT_CDE": "USA", 
        "VHC_MAN_YEAR": "2020", 	 	
        "VHC_PLT_NBR": "ABC123", 
        "VHC_PLT_NAT_CDE": "USA",
    	"VHC_STA_ID": "1",
        "VHC_STA_CDE": "P",
        "VHC_COL_CDE":"",
        "Trips":[
    		{
    			"TRP_DTE":"2024-01-30",
    			"TRP_TIME":"12:00:00.0000000",
    			"TRP_BRD_CDE":"061",
    			"TRP_AIR_CDE":"QTR",
    			"TRP_SHP_CDE":"S12",
    			"TRP_FGT_NBR":"CargoXYZ",
    			"TRP_SHP_NBR":"S12"
    		},
    		{
    			"TRP_DTE":"2024-01-30",
    			"TRP_TIME":"12:00:00.0000000",
    			"TRP_BRD_CDE":"061",
    			"TRP_AIR_CDE":"QTR",
    			"TRP_SHP_CDE":"S12",
    			"TRP_FGT_NBR":"CargoXYZ",
    			"TRP_SHP_NBR":"S12"
    		}
    	]
      }
    ]
    I am using the following procedure to insert the data but getting error that :

    Msg 102, Level 15, State 1, Procedure Usama_Test, Line 81 [Batch Start Line 0]
    Incorrect syntax near ')'.

    Code:
    CREATE OR ALTER    PROCEDURE [dbo].[Usama_Test]
    
    @vehicles_trips_json NVARCHAR(MAX),
    @TRV_ID AS BIGINT
    
       AS
    
    --BEGIN TRANSACTION
    
    	INSERT INTO TVHC 
    		(
    			VHC_TRV_ID,
    			VHC_VTY_CDE,			
    			VHC_NAT_CDE,
    			VHC_MAN_YEAR,
    			VHC_PLT_NBR,
    			VHC_PLT_NAT_CDE,
    			VHC_STY_ID,
    			VHC_STA_CDE,
    			VHC_COL_CDE			
    		)
    		
    		SELECT	
    				@TRV_ID,
    				VHC_VTY_CDE,
    				VHC_NAT_CDE,
    				VHC_MAN_YEAR,
    				VHC_PLT_NBR,
    				VHC_PLT_NAT_CDE,
    				VHC_STY_ID,
    				VHC_STA_CDE,
    				VHC_COL_CDE
    			FROM
    				OPENJSON(@vehicles_trips_json)
    				WITH (  
    					 [VHC_VTY_CDE]   char(3) N'$.VHC_VTY_CDE',
    					 [VHC_NAT_CDE]   char(3) N'$.VHC_NAT_CDE',
    					 [VHC_MAN_YEAR]   char(4) N'$.VHC_MAN_YEAR',
    					 [VHC_PLT_NBR]   varchar(20) N'$.VHC_PLT_NBR',
    					 [VHC_PLT_NAT_CDE]		char(3) N'$.VHC_PLT_NAT_CDE',
    					 [VHC_STY_ID]   int N'$.VHC_STY_ID',
    					 [VHC_STA_CDE]		int N'$.VHC_STA_CDE',
    					 [VHC_COL_CDE]   char(10) N'$.VHC_COL_CDE',
    					 [Trips]   nvarchar(max) N'$.Trips'
    					) AS ROOT_JSON
    
    				OUTER APPLY
    				(
    					INSERT INTO TTRP 
    					(
    						TRP_DTE,
    						TRP_TIME,
    						TRP_VHC_ID,
    						TRP_BRD_CDE,
    						TRP_AIR_CDE,
    						TRP_SHP_CDE,
    						TRP_FGT_NBR,
    						TRP_SHP_NBR
    					)
    				
    					SELECT	
    							TRP_DTE,
    							TRP_TIME,
    							@@IDENTITY,
    							TRP_BRD_CDE,
    							TRP_AIR_CDE,
    							TRP_SHP_CDE,
    							TRP_FGT_NBR,
    							TRP_SHP_NBR
    						FROM
    							OPENJSON(ROOT_JSON.Trips)
    							WITH (  
    								 [TRP_DTE]   date N'$.TRP_DTE',
    								 [TRP_TIME]   time(7) N'$.TRP_TIME',
    								 [TRP_BRD_CDE]   char(3) N'$.TRP_BRD_CDE',
    								 [TRP_AIR_CDE]   char(3) N'$.TRP_AIR_CDE',
    								 [TRP_SHP_CDE]		char(3) N'$.TRP_SHP_CDE',
    								 [TRP_FGT_NBR]		varchar(20) N'$.TRP_FGT_NBR',
    								 [TRP_SHP_NBR]   varchar(20) N'$.TRP_SHP_NBR'
    								) 
    				)	
    --COMMIT TRANSACTION
    Any ideas??
    Last edited by usamaalam; Jan 30th, 2024 at 07:17 AM.

  2. #2
    Fanatic Member
    Join Date
    Jul 2022
    Location
    Buford, Ga USA
    Posts
    631

    Re: Parsing nested json in sql server

    You say you need to do this "I need to insert vehicles into the TVHC table and for each vehicle insert trips into TTRV table." but the Insert Into on the outer apply is inserting into TTRP and not TTRV. Which has the typo?

  3. #3

    Thread Starter
    Frenzied Member usamaalam's Avatar
    Join Date
    Nov 2002
    Location
    Karachi
    Posts
    1,308

    Re: Parsing nested json in sql server

    Quote Originally Posted by jdelano View Post
    You say you need to do this "I need to insert vehicles into the TVHC table and for each vehicle insert trips into TTRV table." but the Insert Into on the outer apply is inserting into TTRP and not TTRV. Which has the typo?
    Sorry it was a type. I corrected.

  4. #4
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    5,268

    Re: Parsing nested json in sql server

    Is there a closing semicolon missing after the last ")"?
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  5. #5
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,190

    Re: Parsing nested json in sql server

    1. No, you cannot OUTER APPLY an INSERT as it has to be a derived table i.e. some kind of SELECT.

    2. You need AS JSON suffix on the [Trips] nvarchar(max) N'$.Trips' in the WITH clause to extract the non-scalar otherwise it will return NULL. This is like JSON_VALUE vs JSON_QUERY -- you use the latter for objects or arrays and the former for scalar types only.

    3. If you are going to insert into mulitple tables (multiple INSERT statements) you'll need a TRANSACTION.

    4. You don't need the JSON Path when column name is the same as the field in the source JSON i.e. this [VHC_VTY_CDE] char(3) N'$.VHC_VTY_CDE' is the same as [VHC_VTY_CDE] char(3) because the column path is implied by the column name when missing.

    5. For the second insert into TTRP you'll need the synthetic PKs of just inserted rows in TVHC which is not present in the JSON

    6. Field VHC_STA_CDE cannot be an INT with values like 'p' in the JSON.

    7. Btw, there is no field VHC_STY_ID in the JSON but VHC_STA_ID

    8. Semicolons are optional in T-SQL (and in JavaScript)

    Try this sample code

    Code:
    DECLARE @JSON VARCHAR(MAX) = '[
      {
        "VHC_VTY_CDE": "CAR1", 
        "VHC_NAT_CDE": "USA", 
        "VHC_MAN_YEAR": "2020",         
        "VHC_PLT_NBR": "ABC123", 
        "VHC_PLT_NAT_CDE": "USA",
        "VHC_STA_ID": "1",
        "VHC_STA_CDE": "P",
        "VHC_COL_CDE":"",
        "Trips":[
            {
                "TRP_DTE":"2024-01-30",
                "TRP_TIME":"12:00:00.0000000",
                "TRP_BRD_CDE":"061",
                "TRP_AIR_CDE":"QTR",
                "TRP_SHP_CDE":"S12",
                "TRP_FGT_NBR":"CargoXYZ",
                "TRP_SHP_NBR":"S12"
            },
            {
                "TRP_DTE":"2024-01-30",
                "TRP_TIME":"12:00:00.0000000",
                "TRP_BRD_CDE":"062",
                "TRP_AIR_CDE":"QTR",
                "TRP_SHP_CDE":"S12",
                "TRP_FGT_NBR":"CargoXYZ",
                "TRP_SHP_NBR":"S12"
            }
        ]
      },
      {
        "VHC_VTY_CDE": "CAR2", 
        "VHC_NAT_CDE": "USA2", 
        "VHC_MAN_YEAR": "2020",         
        "VHC_PLT_NBR": "ABC123", 
        "VHC_PLT_NAT_CDE": "USA",
        "VHC_STA_ID": "1",
        "VHC_STA_CDE": "P",
        "VHC_COL_CDE":"",
        "Trips":[
            {
                "TRP_DTE":"2024-01-30",
                "TRP_TIME":"12:00:00.0000000",
                "TRP_BRD_CDE":"063",
                "TRP_AIR_CDE":"QTR",
                "TRP_SHP_CDE":"S12",
                "TRP_FGT_NBR":"CargoXYZ",
                "TRP_SHP_NBR":"S12"
            },
            {
                "TRP_DTE":"2024-01-30",
                "TRP_TIME":"12:00:00.0000000",
                "TRP_BRD_CDE":"064",
                "TRP_AIR_CDE":"QTR",
                "TRP_SHP_CDE":"S12",
                "TRP_FGT_NBR":"CargoXYZ",
                "TRP_SHP_NBR":"S12"
            }
        ]
      }
    ]'
    DROP TABLE IF EXISTS #TmpTVHC, #TmpTTRP
    
    SELECT      DENSE_RANK() OVER (ORDER BY VHC_VTY_CDE, VHC_NAT_CDE, VHC_MAN_YEAR, VHC_PLT_NBR
                                        , VHC_PLT_NAT_CDE, VHC_STA_ID, VHC_STA_CDE, VHC_COL_CDE) AS VHC_TRV_ID
                , p.*
    INTO        #TmpTVHC
    FROM        OPENJSON(@JSON)
    WITH        (
                VHC_VTY_CDE         NVARCHAR(MAX)
                , VHC_NAT_CDE       NVARCHAR(MAX)
                , VHC_MAN_YEAR      NVARCHAR(MAX)
                , VHC_PLT_NBR       NVARCHAR(MAX)
                , VHC_PLT_NAT_CDE   NVARCHAR(MAX)
                , VHC_STA_ID        NVARCHAR(MAX)
                , VHC_STA_CDE       NVARCHAR(MAX)
                , VHC_COL_CDE       NVARCHAR(MAX)
                ) p
    
    SELECT      DENSE_RANK() OVER (ORDER BY VHC_VTY_CDE, VHC_NAT_CDE, VHC_MAN_YEAR, VHC_PLT_NBR
                                            , VHC_PLT_NAT_CDE, VHC_STA_ID, VHC_STA_CDE, VHC_COL_CDE) AS VHC_TRV_ID
                , s.*
    INTO        #TmpTTRP
    FROM        OPENJSON(@JSON)
    WITH        (
                VHC_VTY_CDE         NVARCHAR(MAX)
                , VHC_NAT_CDE       NVARCHAR(MAX)
                , VHC_MAN_YEAR      NVARCHAR(MAX)
                , VHC_PLT_NBR       NVARCHAR(MAX)
                , VHC_PLT_NAT_CDE   NVARCHAR(MAX)
                , VHC_STA_ID        NVARCHAR(MAX)
                , VHC_STA_CDE       NVARCHAR(MAX)
                , VHC_COL_CDE       NVARCHAR(MAX)
                , Trips             NVARCHAR(MAX)   AS JSON
                ) p
    OUTER APPLY (
                SELECT      *
                FROM        OPENJSON(p.Trips)
                WITH        (
                            TRP_DTE             NVARCHAR(MAX)
                            , TRP_TIME          NVARCHAR(MAX)
                            , TRP_BRD_CDE       NVARCHAR(MAX)
                            , TRP_AIR_CDE       NVARCHAR(MAX)
                            , TRP_SHP_CDE       NVARCHAR(MAX)
                            , TRP_FGT_NBR       NVARCHAR(MAX)
                            , TRP_SHP_NBR       NVARCHAR(MAX)
                            )
                ) s
    
    SELECT * FROM #TmpTVHC
    SELECT * FROM #TmpTTRP
    
    BEGIN TRAN
    
    -- populate TVHC from #TmpTVHC
    -- populate TTRP from #TmpTTRP
    
    --ROLLBACK
    COMMIT
    You'll have to figure out how to populate base tables from the temp tables but so far IMO this is fine as a working example of handling JSON.

    cheers,
    </wqw>

  6. #6

    Thread Starter
    Frenzied Member usamaalam's Avatar
    Join Date
    Nov 2002
    Location
    Karachi
    Posts
    1,308

    Re: Parsing nested json in sql server

    Quote Originally Posted by wqweto View Post
    1. No, you cannot OUTER APPLY an INSERT as it has to be a derived table i.e. some kind of SELECT.

    2. You need AS JSON suffix on the [Trips] nvarchar(max) N'$.Trips' in the WITH clause to extract the non-scalar otherwise it will return NULL. This is like JSON_VALUE vs JSON_QUERY -- you use the latter for objects or arrays and the former for scalar types only.

    3. If you are going to insert into mulitple tables (multiple INSERT statements) you'll need a TRANSACTION.

    4. You don't need the JSON Path when column name is the same as the field in the source JSON i.e. this [VHC_VTY_CDE] char(3) N'$.VHC_VTY_CDE' is the same as [VHC_VTY_CDE] char(3) because the column path is implied by the column name when missing.

    5. For the second insert into TTRP you'll need the synthetic PKs of just inserted rows in TVHC which is not present in the JSON

    6. Field VHC_STA_CDE cannot be an INT with values like 'p' in the JSON.

    7. Btw, there is no field VHC_STY_ID in the JSON but VHC_STA_ID

    8. Semicolons are optional in T-SQL (and in JavaScript)

    Try this sample code

    Code:
    DECLARE @JSON VARCHAR(MAX) = '[
      {
        "VHC_VTY_CDE": "CAR1", 
        "VHC_NAT_CDE": "USA", 
        "VHC_MAN_YEAR": "2020",         
        "VHC_PLT_NBR": "ABC123", 
        "VHC_PLT_NAT_CDE": "USA",
        "VHC_STA_ID": "1",
        "VHC_STA_CDE": "P",
        "VHC_COL_CDE":"",
        "Trips":[
            {
                "TRP_DTE":"2024-01-30",
                "TRP_TIME":"12:00:00.0000000",
                "TRP_BRD_CDE":"061",
                "TRP_AIR_CDE":"QTR",
                "TRP_SHP_CDE":"S12",
                "TRP_FGT_NBR":"CargoXYZ",
                "TRP_SHP_NBR":"S12"
            },
            {
                "TRP_DTE":"2024-01-30",
                "TRP_TIME":"12:00:00.0000000",
                "TRP_BRD_CDE":"062",
                "TRP_AIR_CDE":"QTR",
                "TRP_SHP_CDE":"S12",
                "TRP_FGT_NBR":"CargoXYZ",
                "TRP_SHP_NBR":"S12"
            }
        ]
      },
      {
        "VHC_VTY_CDE": "CAR2", 
        "VHC_NAT_CDE": "USA2", 
        "VHC_MAN_YEAR": "2020",         
        "VHC_PLT_NBR": "ABC123", 
        "VHC_PLT_NAT_CDE": "USA",
        "VHC_STA_ID": "1",
        "VHC_STA_CDE": "P",
        "VHC_COL_CDE":"",
        "Trips":[
            {
                "TRP_DTE":"2024-01-30",
                "TRP_TIME":"12:00:00.0000000",
                "TRP_BRD_CDE":"063",
                "TRP_AIR_CDE":"QTR",
                "TRP_SHP_CDE":"S12",
                "TRP_FGT_NBR":"CargoXYZ",
                "TRP_SHP_NBR":"S12"
            },
            {
                "TRP_DTE":"2024-01-30",
                "TRP_TIME":"12:00:00.0000000",
                "TRP_BRD_CDE":"064",
                "TRP_AIR_CDE":"QTR",
                "TRP_SHP_CDE":"S12",
                "TRP_FGT_NBR":"CargoXYZ",
                "TRP_SHP_NBR":"S12"
            }
        ]
      }
    ]'
    DROP TABLE IF EXISTS #TmpTVHC, #TmpTTRP
    
    SELECT      DENSE_RANK() OVER (ORDER BY VHC_VTY_CDE, VHC_NAT_CDE, VHC_MAN_YEAR, VHC_PLT_NBR
                                        , VHC_PLT_NAT_CDE, VHC_STA_ID, VHC_STA_CDE, VHC_COL_CDE) AS VHC_TRV_ID
                , p.*
    INTO        #TmpTVHC
    FROM        OPENJSON(@JSON)
    WITH        (
                VHC_VTY_CDE         NVARCHAR(MAX)
                , VHC_NAT_CDE       NVARCHAR(MAX)
                , VHC_MAN_YEAR      NVARCHAR(MAX)
                , VHC_PLT_NBR       NVARCHAR(MAX)
                , VHC_PLT_NAT_CDE   NVARCHAR(MAX)
                , VHC_STA_ID        NVARCHAR(MAX)
                , VHC_STA_CDE       NVARCHAR(MAX)
                , VHC_COL_CDE       NVARCHAR(MAX)
                ) p
    
    SELECT      DENSE_RANK() OVER (ORDER BY VHC_VTY_CDE, VHC_NAT_CDE, VHC_MAN_YEAR, VHC_PLT_NBR
                                            , VHC_PLT_NAT_CDE, VHC_STA_ID, VHC_STA_CDE, VHC_COL_CDE) AS VHC_TRV_ID
                , s.*
    INTO        #TmpTTRP
    FROM        OPENJSON(@JSON)
    WITH        (
                VHC_VTY_CDE         NVARCHAR(MAX)
                , VHC_NAT_CDE       NVARCHAR(MAX)
                , VHC_MAN_YEAR      NVARCHAR(MAX)
                , VHC_PLT_NBR       NVARCHAR(MAX)
                , VHC_PLT_NAT_CDE   NVARCHAR(MAX)
                , VHC_STA_ID        NVARCHAR(MAX)
                , VHC_STA_CDE       NVARCHAR(MAX)
                , VHC_COL_CDE       NVARCHAR(MAX)
                , Trips             NVARCHAR(MAX)   AS JSON
                ) p
    OUTER APPLY (
                SELECT      *
                FROM        OPENJSON(p.Trips)
                WITH        (
                            TRP_DTE             NVARCHAR(MAX)
                            , TRP_TIME          NVARCHAR(MAX)
                            , TRP_BRD_CDE       NVARCHAR(MAX)
                            , TRP_AIR_CDE       NVARCHAR(MAX)
                            , TRP_SHP_CDE       NVARCHAR(MAX)
                            , TRP_FGT_NBR       NVARCHAR(MAX)
                            , TRP_SHP_NBR       NVARCHAR(MAX)
                            )
                ) s
    
    SELECT * FROM #TmpTVHC
    SELECT * FROM #TmpTTRP
    
    BEGIN TRAN
    
    -- populate TVHC from #TmpTVHC
    -- populate TTRP from #TmpTTRP
    
    --ROLLBACK
    COMMIT
    You'll have to figure out how to populate base tables from the temp tables but so far IMO this is fine as a working example of handling JSON.

    cheers,
    </wqw>
    Thanks for your time and effort, I'll put this in my actual procedure with INSERT into the table and test it.

  7. #7

    Re: Parsing nested json in sql server

    Is there a missing closing semicolon after the last ")" in your SQL Server code, and have you verified its presence?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width