复制 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
来获取插入的行。
可以按照ORDER BY c.QuantlistAttributeId ASC
的顺序插入数据到QuantlistAttribute
有一个临时 table/table 变量,其中 3 列
- 一个id标识列
- 新的 QuantlistAttributeId
- 旧的 QuantlistAttributeId。
使用 OUTPUT
将 QuantlistAttribute 的新标识值插入临时 table/table 变量。
新 ID 的生成顺序与 c.QuantlistAttributeId
相同
使用QuantlistAttributeId
排序的row_number()
根据row_number()
和[=匹配旧的QuantlistAttributeId
和新的QuantlistAttributeIds
table 变量的 21=] 并更新 table 变量
中的值或旧的 QuantlistAttributeId
使用临时 table 和 join
与 AttributeReference
并一次性插入记录。
注:
ORDER BY
在 INSERT INTO SELECT
和 ROW_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
希望这对您有所帮助。
我有一个 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
来获取插入的行。
可以按照
ORDER BY c.QuantlistAttributeId ASC
的顺序插入数据到有一个临时 table/table 变量,其中 3 列
- 一个id标识列
- 新的 QuantlistAttributeId
- 旧的 QuantlistAttributeId。
使用
OUTPUT
将 QuantlistAttribute 的新标识值插入临时 table/table 变量。 新 ID 的生成顺序与c.QuantlistAttributeId
相同
使用
QuantlistAttributeId
排序的row_number()
根据row_number()
和[=匹配旧的QuantlistAttributeId
和新的QuantlistAttributeIds
table 变量的 21=] 并更新 table 变量 中的值或旧的 QuantlistAttributeId
使用临时 table 和
join
与AttributeReference
并一次性插入记录。
QuantlistAttribute
注:
ORDER BY
在 INSERT INTO SELECT
和 ROW_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
希望这对您有所帮助。