我有一个父表,表示一个文件,表中的每条记录都有一个子表中的 n 子记录。每个子记录都可以包含 n 孙子记录。这些记录处于发布的状态。当用户想要修改已发布的文档时,我们需要克隆父项及其所有子项和孙项。
表结构如下所示:
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])
);
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]),
)
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
表格有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
条记录,如何克隆参考表中的记录并将它们与我刚刚插入QuantlistAttribute
表中的新记录相匹配?
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.
我以为我可以使用一些临时链接表来保存旧属性id和新属性id。我不知道如何将旧的属性ID与新的属性ID一起插入到临时表中。通过QuantlistId插入现有属性非常简单,但我无法弄清楚如何确保以某种方式将正确的新旧Id连接在一起,以便可以正确克隆AttributeReference
表。如果我可以将QuantlistAttribute
新旧Id链接起来,我可以加入该临时表并找出如何将新克隆的引用与新克隆的属性的关系恢复。
对此的任何帮助都会很棒。我花了最后一天半试图弄清楚这一点没有运气:/
请原谅一些SQL的不一致之处。我快速重新写了sql,修剪了很多额外的列,相关表和这个问题不需要的约束。
经过一番挖掘后,我发现OUTPUT可能对此有用。有没有办法使用OUTPUT将我刚刚插入的QuantlistAttributeId
条记录映射到它们来自的QuantlistAttributeId
?
答案 0 :(得分:3)
您可以使用OUTPUT
来获取插入的行。
您可以根据QuantlistAttribute
ORDER BY c.QuantlistAttributeId ASC
有一个3列
的临时表/表变量使用OUTPUT
将QuantlistAttribute的新标识值插入临时表/表变量。
新ID的生成顺序与c.QuantlistAttributeId
使用row_number()
订购的QuantlistAttributeId
来匹配旧QuantlistAttributeId
和新QuantlistAttributeIds
基于row_number()
和id
的{{1}}表变量并更新表变量
使用临时表和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
希望这有帮助。