1

I feel I need to start this question by saying I have a very limited knowledge of SQL, therefore the solution I am trying to implement has come about from a lot of reading and lack of experience. So if what I am requesting is the wrong way to complete my task please advise accordingly (rather than accepting that I must have some valid reason for creating a potentially really odd SQL statement).

The problem

I have two tables Rooms and RoomPhotoUrls I am receiving the data for these in a table value parameter (TVP). The TVP can have n rooms and each room can have n images. I would like to be able insert all rooms then get the id for each room inserted so that I can insert the images and associate them to the correct room

Why I've chosen to try this as a potential solution

As you can see from the rooms table it's a child of another table(properties). The properties tables also has other tables to populate so I want to make a single call to the database passing my property object and have SQL manage all the data inserts\updates rather than making several round trips.

Having limited knowledge of SQL I did a lot of reading and found TVP's which seem to be what I need to use. I also read about passing xml parameters, but I got the impression that passing xml was only a solution as TVP hadn't been introduced, so I went with the TVP option.

The code I have added

Below you will see the following:

  • RoomPhotoUrls Table schema
  • Rooms Table schema
  • TVP schema
  • Some sample data
  • My stored procedure
  • The result of my stored procedure

Table schemas

CREATE TABLE [dbo].[RoomPhotoUrls]
(
    [RoomPhotoUrlsId] [int] IDENTITY(1,1) NOT NULL,
    [RoomId] [int] NULL,
    [Url] [varchar](max) NULL,

    CONSTRAINT [PK_RoomPhotoUrls] 
        PRIMARY KEY CLUSTERED ([RoomPhotoUrlsId] ASC)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

CREATE TABLE [dbo].[Rooms]
(
    [RoomId] [int] NULL,
    [PropertyId] [int] NULL,
    [RoomName] [varchar](120) NULL,
    [RoomDescription] [varchar](max) NULL,
    [RoomLength] [decimal](5, 2) NULL,
    [RoomWidth] [decimal](5, 2) NULL,
    [Url] [varchar](max) NULL

    CONSTRAINT [PK_Rooms] 
        PRIMARY KEY CLUSTERED ([RoomId] ASC)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Table-valued parameter

CREATE TYPE [dbo].[RoomTableType] AS TABLE(
    [RoomId] [int] NULL,
    [PropertyId] [int] NULL,
    [RoomName] [varchar](120) NULL,
    [Url] [varchar](max) NULL
)

Sample data

USE MyDb

DECLARE @roomTableType as RoomTableType

INSERT INTO @roomTableType ([RoomName], [Url])
VALUES  ('Room 1', 'Url1'), ('Room 1', 'Url2'),     
        ('Room 2', 'Url3'), ('Room 2', 'Url4'),
        ('Room 3', 'Url5'), ('Room 3', 'Url6'),     
        ('Room 3', 'Url7')

EXEC dbo.phsp_CreatePropertyRooms @roomTableType, 1212

The result

Rooms

RoomId  PropertyId  RoomName    RoomDescription RoomLength  RoomWidth
---------------------------------------------------------------------
1259    1212        Room 3      test            1.00        1.00
1258    1212        Room 2      test            1.00        1.00
1257    1212        Room 1      test            1.00        1.00

RoomPhotoUrls

RoomPhotoUrlsId RoomId  Url
----------------------------
1290            1257    Url7
1289            1257    Url6
1288            1257    Url5
1287            1257    Url4
1286            1257    Url3
1285            1257    Url2
1284            1257    Url1

My stored procedure

USE MyDb
GO

/****** Object:  StoredProcedure [dbo].[phsp_CreatePropertyRooms]    Script Date: 21/02/2018 23:02:24 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

-- =============================================
-- Author:      Tony Simpson
-- Create date: 04/12/17
-- Description: Create the rooms and images associated
-- =============================================
ALTER PROCEDURE [dbo].[phsp_CreatePropertyRooms]
    @roomsTableType [dbo].[RoomTableType] READONLY,
    @propertyId INT
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @distinctRooms TABLE ([RoomId] int, [RoomName] varchar(120), [RoomDescription] varchar(MAX), [RoomLength] decimal, [RoomWidth] decimal)
    DECLARE @insertedRooms TABLE ([RoomId] int, [RoomName] varchar(120), [RoomDescription] varchar(MAX), [RoomLength] decimal, [RoomWidth] decimal)
    DECLARE @roomsTableTypeCopy TABLE ([RoomId] int, [RoomName] varchar(120), [RoomDescription] varchar(MAX), [RoomLength] decimal, [RoomWidth] decimal, [Url] Varchar(MAX))

    --get distinct rooms
    INSERT INTO  @distinctRooms (RoomName, RoomDescription, RoomLength, RoomWidth)
        SELECT DISTINCT
                 r.RoomName
                ,r.RoomDescription
                ,r.RoomLength
                ,r.RoomWidth
        FROM     @roomsTableType r

    --insert into rooms table and save details in @insertedRooms
    INSERT  INTO Rooms (RoomName, RoomDescription, RoomLength, RoomWidth, PropertyId)
    OUTPUT  inserted.RoomId, inserted.RoomName, inserted.RoomDescription, inserted.RoomLength, inserted.RoomWidth INTO @insertedRooms
        SELECT  RoomName,
                RoomDescription,
                RoomLength,
                RoomWidth,
                @propertyId
        FROM    @distinctRooms

    --populate @propertyTableTypeCopy so it can be updated
    INSERT INTO @roomsTableTypeCopy (
        [RoomId]
        ,[RoomName]
        ,[RoomDescription]
        ,[RoomLength]
        ,[RoomWidth]
        ,[url])
        SELECT  RoomId
                ,RoomName
                ,RoomDescription
                ,RoomLength
                ,RoomWidth
                ,[Url]
        FROM    @roomsTableType

    --update rooms in @propertyTableTypeCopy with room id
    UPDATE  @roomsTableTypeCopy
    SET     [RoomId] = SR.RoomId
    FROM    @insertedRooms SR
    CROSS APPLY (
        SELECT  [RoomId]
                ,[RoomName]
                ,[RoomDescription]
                ,[RoomLength]
                ,[RoomWidth]
        FROM    @insertedRooms
        WHERE   SR.RoomName = RoomName
            AND SR.RoomLength = RoomLength
            AND SR.RoomDescription = RoomDescription
            AND SR.RoomWidth = RoomWidth
    ) AS r;

    --add to table
    INSERT INTO RoomPhotoUrls (RoomId, [Url])
    SELECT [RoomId], [url]
    FROM @roomsTableTypeCopy
END
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
tony09uk
  • 2,841
  • 9
  • 45
  • 71
  • Even though this question is an exact duplicate, I still upvoted it since it's a grate example on how to ask questions. It's very clear, very well formed, and contains all the relevant data. Kudos. – Zohar Peled Feb 23 '18 at 07:13
  • Thank you for the direction. I was able to solve it by following the first thread. Apologies for the duplication – tony09uk Feb 23 '18 at 22:05
  • Glad to help ;-) – Zohar Peled Feb 24 '18 at 06:24

0 Answers0