Вставить в таблицу словаря при чтении из таблиц сервера. json в sql - PullRequest
0 голосов
/ 10 июля 2020

Мне нужно разобрать. json файл в SQL базу данных сервера. У меня есть 3 таблицы: Booking (резервирование магазинов, одно бронирование может иметь несколько комнат), Room (складские помещения), RoomBookingHistory (связь магазина между Booking и Room). Вот пример файла. json:

[
  {
    "BookingName": "Egypt, SES, 3 persons, 14 days",
    "Paid": "0",
    "Active": "1",
    "DateOfBooking": "2020/05/07 19:35:02",
    "UserLogin": "Alex222",
    "Rooms": [
      {
        "RoomName": "SESBR23",
        "Capacity": "2",
        "Price": "120",
        "Stars": "3"
      },
      {
        "RoomName": "SESBR21",
        "Capacity": "1",
        "Price": "60",
        "Stars": "4"
      }
    ],
    "FlightNumber": "FO23465",
    "ManagerLogin": "Manger_Egypt_1"
  },
  {
    "BookingName": "Egypt, Hurgada, 3 persons, 7 days",
    "Paid": "0",
    "Active": "1",
    "DateOfBooking": "2020/05/07 17:35:02",
    "UserLogin": "Super_tourist",
    "Rooms": [
      {
        "RoomName": "HGST45",
        "Capacity": "3",
        "Price": "250",
        "Stars": "5"
      }
    ],
    "FlightNumber": "HR5665",
    "ManagerLogin": "Manger_Egypt_2"
  }
]

Используя созданную процедуру сохранения, я прочитал. json и вставил в таблицу Booking Bookings и в таблицу Room Rooms из. json. Во время синтаксического анализа мне нужно вставить в записи RoomBookingHistory и связать каждое бронирование с комнатами из файла, используя сгенерированный идентификатор во время записи из. json.

RoomBookingHistory
    RoomBookingId   int             not null     identity(1,1),
    RoomId          int,
    BookingId       int

Как написать sql для вставки в RoomBookingHistory правильные связанные идентификаторы ?

Вот код sp:

drop procedure  if exists dbo.usp_ImportBookingData
go
create procedure dbo.usp_ImportBookingData
    @parametrs nvarchar(max)
    
as
begin
    set nocount on

    create table #Booking
    (
            BookingId       int             not null     identity(1,1),
            BookingName     varchar(30),
            Paid            bit,
            Active          bit,
            DateOfBooking   datetime,
            UserId          int,
            FlightId        int,
            ManagerId       int,
            Rooms           nvarchar(max)   
    )

    insert into #Booking
    (       
        BookingName,
        Paid,
        Active,
        DateOfBooking,
        Rooms
    )
    select      
        b.BookingName,
        b.Paid,
        b.Active,
        CONVERT(DATETIME, b.DateOfBooking),
        b.Rooms
    from openjson(@parametrs)
        with
        (
            BookingName         varchar(30)     N'$.BookingName',
            Paid                bit             N'$.Paid',
            Active              bit             N'$.Active',
            DateOfBooking       datetime        N'$.DateOfBooking',
            Rooms               nvarchar(max)   N'$.Rooms' as json
        ) b

    insert into dbo.Booking
    (   
        BookingName,
        Paid,
        Active,
        DateOfBooking
    )
    select
        b.BookingName,
        b.Paid,
        b.Active,
        CONVERT(DATETIME, b.DateOfBooking)
    from #Booking b

    create table #Rooms
    (
        RoomId              int         not null     identity(1,1),
        RoomName            varchar(30),
        Capacity            int,
        Price               int,
        Stars               int,
        HotelId             int
    )

    insert into #Rooms
    (
        RoomName,
        Capacity,
        Price,
        Stars
    )
    select
        br.RoomName,
        br.Capacity,
        br.Price,
        br.Stars
    from #Booking b
    cross apply openjson(b.Rooms)
        with
        (
            RoomName            varchar(30)     N'$.RoomName',
            Capacity            int             N'$.Capacity',
            Price               int             N'$.Price',
            Stars               int             N'$.Stars'

        ) br
    insert into dbo.Room
    (
        RoomName,
        Capacity,
        Price,
        Stars
    )
    select
        br.RoomName,
        br.Capacity,
        br.Price,
        br.Stars
    from #Rooms br

1 Ответ

0 голосов
/ 12 июля 2020

Вы можете использовать синтаксис MERGE INTO... OUTPUT INTO..., который позволяет захватывать не только вставленные столбцы таблицы (например, INSERT INTO... OUTPUT INTO...), но и другие столбцы из источника таблицы. (в отличие от INSERT INTO... OUTPUT INTO...).

В приведенном ниже коде:

  • В первом операторе MERGE я использую переменную @table для захвата dbo.Booking.BookingId вместе с JSON blob для соответствующей комнаты (ей).
  • Во втором операторе MERGE выведите BookingId (полученный из первого MERGE) и dbo.Room.RoomId непосредственно в таблицу dbo.RoomBookingHistory.
create procedure dbo.usp_ImportBookingData
    @parametrs nvarchar(max)
as
begin
    set nocount on

    declare @InsertedBookings table (
        BookingId int not null,
        Rooms nvarchar(max)
    );

    merge into dbo.Booking as Target
    using (
        select BookingName, Paid, Active, DateOfBooking, Rooms
        from openjson(@parametrs) with (
            BookingName         varchar(30)     N'$.BookingName',
            Paid                bit             N'$.Paid',
            Active              bit             N'$.Active',
            DateOfBooking       datetime        N'$.DateOfBooking',
            Rooms               nvarchar(max)   N'$.Rooms' as json
        )
    ) as Source
    on (0=1) -- force "not matched" for insert
    when not matched then
        insert (BookingName, Paid, Active, DateOfBooking)
        values (BookingName, Paid, Active, DateOfBooking)
    output Inserted.BookingId, Source.Rooms into @InsertedBookings;

    merge into dbo.Room as Target
    using (
        select BookingId, RoomName, Capacity, Price, Stars
        from @InsertedBookings
        cross apply openjson(Rooms) with (
            RoomName            varchar(30)     N'$.RoomName',
            Capacity            int             N'$.Capacity',
            Price               int             N'$.Price',
            Stars               int             N'$.Stars'
        )
    ) as Source
    on (0=1) -- force "not matched" for insert
    when not matched then
        insert (RoomName, Capacity, Price, Stars)
        values (RoomName, Capacity, Price, Stars)
    output Inserted.RoomId, Source.BookingId into dbo.RoomBookingHistory (RoomId, BookingId);
end

А затем с его помощью ...

declare @parametrs nvarchar(max) = N'[
  {
    "BookingName": "Egypt, SES, 3 persons, 14 days",
    "Paid": "0",
    "Active": "1",
    "DateOfBooking": "2020/05/07 19:35:02",
    "UserLogin": "Alex222",
    "Rooms": [
      {
        "RoomName": "SESBR23",
        "Capacity": "2",
        "Price": "120",
        "Stars": "3"
      },
      {
        "RoomName": "SESBR21",
        "Capacity": "1",
        "Price": "60",
        "Stars": "4"
      }
    ],
    "FlightNumber": "FO23465",
    "ManagerLogin": "Manger_Egypt_1"
  },
  {
    "BookingName": "Egypt, Hurgada, 3 persons, 7 days",
    "Paid": "0",
    "Active": "1",
    "DateOfBooking": "2020/05/07 17:35:02",
    "UserLogin": "Super_tourist",
    "Rooms": [
      {
        "RoomName": "HGST45",
        "Capacity": "3",
        "Price": "250",
        "Stars": "5"
      }
    ],
    "FlightNumber": "HR5665",
    "ManagerLogin": "Manger_Egypt_2"
  }
]';

exec dbo.usp_ImportBookingData @parametrs=@parametrs;

select * from dbo.Booking;
select * from dbo.Room;
select * from dbo.RoomBookingHistory;

Выдает результаты ...

BookingId   BookingName                    Paid  Active DateOfBooking
----------- ------------------------------ ----- ------ -----------------------
1           Egypt, SES, 3 persons, 14 days 0     1      2020-05-07 19:35:02.000
2           Egypt, Hurgada, 3 persons, 7 d 0     1      2020-05-07 17:35:02.000

(2 rows affected)

RoomId      RoomName                       Capacity    Price       Stars
----------- ------------------------------ ----------- ----------- -----------
1           SESBR23                        2           120         3
2           SESBR21                        1           60          4
3           HGST45                         3           250         5

(3 rows affected)

RoomBookingId RoomId      BookingId
------------- ----------- -----------
1             1           1
2             2           1
3             3           2

(3 rows affected)
...