复制 parent、child 和 grandchild 记录

Duplicating parent, child and grandchild records

我有一个 parent table 表示文档 of-sorts,table 中的每条记录都有 n children记录在childtable。每条child条记录可以有n条grandchild条记录。这些记录处于 已发布 状态。当用户想要修改已发布的文档时,我们需要克隆 parent 及其所有 children 和 grandchildren.

table 结构如下所示:

Parent

CREATE TABLE [ql].[Quantlist] (
    [QuantlistId]   INT           IDENTITY (1, 1) NOT NULL,
    [StateId]       INT           NOT NULL,
    [Title]         VARCHAR (500) NOT NULL,
    CONSTRAINT [PK_Quantlist] PRIMARY KEY CLUSTERED ([QuantlistId] ASC),
    CONSTRAINT [FK_Quantlist_State] FOREIGN KEY ([StateId]) REFERENCES [ql].[State] ([StateId])
);

Child

CREATE TABLE [ql].[QuantlistAttribute]
(
    [QuantlistAttributeId] INT IDENTITY (1, 1),
    [QuantlistId] INT NOT NULL,
    [Narrative] VARCHAR (500) NOT NULL,
    CONSTRAINT [PK_QuantlistAttribute] PRIMARY KEY ([QuantlistAttributeId]), 
    CONSTRAINT [FK_QuantlistAttribute_QuantlistId] FOREIGN KEY ([QuantlistId]) REFERENCES [ql].[Quantlist]([QuantlistId]),
)

盛大child

CREATE TABLE [ql].[AttributeReference]
(
    [AttributeReferenceId] INT IDENTITY (1, 1),
    [QuantlistAttributeId] INT NOT NULL,
    [Reference] VARCHAR (250) NOT NULL,
    CONSTRAINT [PK_QuantlistReference] PRIMARY KEY ([AttributeReferenceId]), 
    CONSTRAINT [FK_QuantlistReference_QuantlistAttribute] FOREIGN KEY ([QuantlistAttributeId]) REFERENCES [ql].[QuantlistAttribute]([QuantlistAttributeId]),
)

在我的存储过程中,我传入 QuantlistId 我想克隆为 @QuantlistId。由于 QuantlistAttribute table 有一个 ForeignKey 我也可以很容易地克隆它。

INSERT INTO [ql].[Quantlist] (
    [StateId],
    [Title],
) SELECT 
    1,
    Title,
    FROM [ql].[Quantlist]
    WHERE QuantlistId = @QuantlistId

SET @ClonedId = SCOPE_IDENTITY()

INSERT INTO ql.QuantlistAttribute(
        QuantlistId
        ,Narrative)
    SELECT 
        @ClonedId,
        Narrative,
    FROM ql.QuantlistAttribute
    WHERE QuantlistId = @QuantlistId

麻烦归结到 AttributeReference。如果我克隆了 30 QuantlistAttribute 条记录,我如何克隆引用 table 中的记录并将它们与我刚刚插入到 QuantlistAttribute table 中的新记录相匹配?

    INSERT INTO ql.AttributeReference(
            QuantlistAttributeId,
            Reference,)
        SELECT 
            QuantlistAttributeId,
            Reference,
        FROM ql.QuantlistReference
        WHERE ??? I don't have a key to go off of for this.

我想我可以用一些临时的 linking table 来做到这一点,它包含旧的属性 ID 和新的属性 ID。我不知道如何将旧属性 ID 与新属性 ID 一起插入到临时 table 中。通过 QuantlistId 插入现有属性很容易,但我不知道如何确保 link 以某种方式将正确的新旧 ID 放在一起,以便 AttributeReference table可以正确克隆。如果我能得到 QuantlistAttribute 新旧 Id 的 linked,我就可以加入那个临时 table 并弄清楚如何恢复新克隆的引用与新克隆的引用的关系属性。

任何对此的帮助都会很棒。我花了最后一天半的时间试图解决这个问题,但没有运气:/

请原谅一些 SQL 不一致的地方。我 re-wrote 很快就 sql 了,删掉了很多额外的列,related-tables 和这个问题不需要的约束。

编辑

在深入研究之后,我发现 OUTPUT 可能对此有用。有没有办法使用 OUTPUT 将我刚刚插入的 QuantlistAttributeId 记录映射到它们起源的 QuantlistAttributeId

您可以使用 OUTPUT 来获取插入的行。

  1. 可以按照ORDER BY c.QuantlistAttributeId ASC

  2. 的顺序插入数据到QuantlistAttribute
  3. 有一个临时 table/table 变量,其中 3 列

    • 一个id标识列
    • 新的 QuantlistAttributeId
    • 旧的 QuantlistAttributeId。
  4. 使用 OUTPUT 将 QuantlistAttribute 的新标识值插入临时 table/table 变量。 新 ID 的生成顺序与 c.QuantlistAttributeId

  5. 相同
  6. 使用QuantlistAttributeId排序的row_number()根据row_number()和[=匹配旧的QuantlistAttributeId和新的QuantlistAttributeIds table 变量的 21=] 并更新 table 变量

  7. 中的值或旧的 QuantlistAttributeId
  8. 使用临时 table 和 joinAttributeReference 并一次性插入记录。

注: ORDER BYINSERT INTO SELECTROW_NUMBER() 期间需要匹配旧的 QuantlistAttributeId 因为看你的问题,似乎没有其他逻辑键将新旧记录映射在一起。

查询上述步骤

DECLARE @ClonedId INT,@QuantlistId INT = 0

INSERT INTO [ql].[Quantlist] (
    [StateId],
    [Title]
) SELECT 
    1,
    Title
    FROM [ql].[Quantlist]
    WHERE QuantlistId = @QuantlistId

SET @ClonedId = SCOPE_IDENTITY()
--Define a table variable to store the new QuantlistAttributeID and use it to map with the Old QuantlistAttributeID
DECLARE @temp TABLE(id int identity(1,1), newAttrID INT,oldAttrID INT)

INSERT INTO ql.QuantlistAttribute(
        QuantlistId
        ,Narrative)
        --New QuantlistAttributeId are created in the same order as old QuantlistAttributeId  because of ORDER BY
        OUTPUT inserted.QuantlistAttributeId,NULL INTO @temp
    SELECT 
        @ClonedId,
        Narrative
    FROM ql.QuantlistAttribute c
    WHERE QuantlistId = @QuantlistId
    --This is required to keep new ids generated in the same order as old
    ORDER BY c.QuantlistAttributeId ASC

    ;WITH CTE AS
    (
        SELECT c.QuantlistAttributeId,
        --Use ROW_NUMBER to get matching id which is same as the one generated in @temp
        ROW_NUMBER()OVER(ORDER BY c.QuantlistAttributeId ASC) id
        FROM ql.QuantlistAttribute c
        WHERE QuantlistId = @QuantlistId
    )
    --Update the old value in @temp 
    UPDATE T
    SET oldAttrID = CTE.QuantlistAttributeId
    FROM @temp T
    INNER JOIN CTE ON T.id = CTE.id


INSERT INTO ql.AttributeReference(
            QuantlistAttributeId,
            Reference)
        SELECT 
            T.NewAttrID,
            Reference
        FROM ql.AttributeReference R
        --Use OldAttrID to join with ql.AttributeReference and insert NewAttrID
        INNER JOIN @temp T
        ON T.oldAttrID = R.QuantlistAttributeId

希望这对您有所帮助。