在单个存储过程中添加多个父记录和多个子记录

时间:2018-02-22 23:20:58

标签: sql-server tsql

我觉得我需要通过说我对SQL的知识非常有限来开始这个问题,因此我试图实现的解决方案来自于大量的阅读和缺乏经验。因此,如果我要求的是完成任务的错误方法,请相应地提出建议(而不是接受我必须有一些有效的理由来创建可能非常奇怪的SQL语句)。

问题

我有两个表RoomsRoomPhotoUrls我在表值参数(TVP)中接收这些表的数据。 TVP可以有 n 房间,每个房间可以有 n 图像。我希望能够插入所有房间,然后获取插入的每个房间的ID,以便我可以插入图像并将它们关联到正确的房间

为什么我选择将此作为潜在的解决方案

从房间表中可以看出,它是另一个桌子的孩子(属性)。属性表还有其他要填充的表,所以我想通过我的property对象对数据库进行一次调用,并让SQL管理所有数据插入\更新,而不是多次往返。

对SQL的了解有限,我做了很多阅读,发现TVP似乎是我需要使用的。我还读到了关于传递xml参数的信息,但我觉得传递xml只是一个解决方案,因为没有引入TVP,所以我选择了TVP选项。

我添加的代码

您将在下面看到以下内容:

  • RoomPhotoUrls表架构
  • 会议室表架构
  • TVP架构
  • 一些示例数据
  • 我的存储过程
  • 我的存储过程的结果

表架构

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]

表值参数

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

示例数据

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

结果

房间

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

我的存储过程

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

0 个答案:

没有答案