我正在尝试跟踪商业建筑结构中的物品(特别是混凝土覆层)。
为了在数据库中构建面板以便跟踪它们时更容易,我希望能够复制一个块(因为10次中有9次,每个块都有相同的细微变化)
就表而言 -
块
Blocks.BlockID,
Blocks.BlockName,
Blocks.BlockDescription,
Projects.ProjectID
立面
Elevations.ElevationID,
Elevations.ElevationName,
Elevations.ElevationDescription,
Blocks.BlockID
地面
Floors.FloorID,
Floors.FloorName,
Floors.FloorDescription,
Elevations.ElevationID
面板
Panels.PanelID,
Panels.PanelName,
Panels.PanelDescription,
Floors.FloorID
如果我复制一个块,则需要
如果您需要了解其他任何内容,请告诉我,感谢您提前提供帮助!
我的尝试(在之前的建议之后)
DECLARE @blockToCopy int = 1
DECLARE @BlockOutput table
( BlockID int);
DECLARE @ElevationsOutput table
( ElevationID int, BlockID int );
DECLARE @FloorsOutput table
( FloorID int, ElevationID int );
DECLARE @ItemsOutput table
( ItemID int, FloorID int );
INSERT INTO Blocks
(ProjectID,BlockName,BlockDescription)
OUTPUT
INSERTED.BlockID
INTO @BlockOutput
SELECT ProjectID,'NewNameTest','NewDescTest'
from Blocks
WHERE BlockID=@blockToCopy
INSERT INTO Elevations
(BlockID,ElevationName,ElevationDescription)
OUTPUT
INSERTED.ElevationID,
INSERTED.BlockID
INTO @ElevationsOutput
SELECT (SELECT BlockID from @BlockOutput),ElevationName,ElevationDescription
from Elevations
WHERE BlockID=@blockToCopy
INSERT INTO Floors
(ElevationID,FloorName,FloorDescription)
OUTPUT
INSERTED.FloorID,
INSERTED.ElevationID
INTO @FloorsOutput
SELECT (SELECT top 1 ElevationID from @ElevationsOutput order by ElevationID desc), FloorName,FloorDescription
from Floors
WHERE ElevationID in (SELECT ElevationID from @ElevationsOutput)
在第二个级联(尝试复制每个高程内的所有楼层)之后出错。我知道为什么它会出错(而不是将原始ID和新ID一起列出来复制到,我自己输出新的ID因此它没有任何要复制的东西,因为它们还不存在)但我不知道如何解决它。
答案 0 :(得分:1)
我认为Blocks.BlockID
,Elevations.ElevationID
,Floors.FloorID
,Panels.PanelID
是主键并自动生成IDENTITY
。
Block
有很多Elevations
。Elevation
有很多Floors
。Floor
有很多Panels
。我将MERGE
与OUTPUT
条款一起使用。
MERGE
可以INSERT
,UPDATE
和DELETE
行。
在这种情况下,我们只需要INSERT
。
1=0
始终为false,因此始终会执行NOT MATCHED BY TARGET
部分。
一般来说,可能还有其他分支,请参阅docs。
WHEN MATCHED
通常用于UPDATE
;
WHEN NOT MATCHED BY SOURCE
通常用于DELETE
,但我们在这里不需要它们。
这种令人费解的MERGE
形式相当于简单INSERT
,
但与简单INSERT
不同,它的OUTPUT
子句允许引用我们需要的列。
它允许从源表和目标表中检索列,从而节省映射
旧现有ID与IDENTITY
生成的新ID之间。
阻止强>
复制一个Block
,并记住新ID
的{{1}}。
我们可以在这里使用简单的Block
和INSERT
,
因为SCOPE_IDENTITY
是主键,只能插入一行。
BlockID
<强>立面强>
从旧DECLARE @blockToCopy int = 1;
DECLARE @VarNewBlockID int;
INSERT INTO Blocks
(ProjectID
,BlockName
,BlockDescription)
SELECT
ProjectID
,'NewNameTest'
,'NewDescTest'
FROM Blocks
WHERE Blocks.BlockID = @blockToCopy
;
SET @VarNewBlockID = SCOPE_IDENTITY();
复制Elevations
并将其分配给新的Block
。
请记住旧Block
与IDs
中新生成的IDs
之间的映射。
@MapElevations
<强>地面强>
使用新旧DECLARE @MapElevations TABLE(OldElevationID int, NewElevationID int);
MERGE INTO Elevations
USING
(
SELECT
ElevationID
,@VarNewBlockID AS BlockID
,ElevationName
,ElevationDescription
FROM Elevations
WHERE Elevations.BlockID = @blockToCopy
) AS Src
ON 1 = 0
WHEN NOT MATCHED BY TARGET THEN
INSERT
(BlockID
,ElevationName
,ElevationDescription)
VALUES
(Src.BlockID
,Src.ElevationName
,Src.ElevationDescription)
OUTPUT
Src.ElevationID AS OldElevationID
,inserted.ElevationID AS NewElevationID
INTO @MapElevations(OldElevationID, NewElevationID)
;
之间的映射复制Floors
。
请记住旧ElevationID
与IDs
中新生成的IDs
之间的映射。
@MapFloors
<强>面板强>
使用新旧DECLARE @MapFloors TABLE(OldFloorID int, NewFloorID int);
MERGE INTO Floors
USING
(
SELECT
Floors.FloorID
,M.NewElevationID AS ElevationID
,Floors.FloorName
,Floors.FloorDescription
FROM
Floors
INNER JOIN Elevations ON Elevations.ElevationID = Floors.ElevationID
INNER JOIN @MapElevations AS M ON M.OldElevationID = Elevations.ElevationID
WHERE Elevations.BlockID = @blockToCopy
) AS Src
ON 1 = 0
WHEN NOT MATCHED BY TARGET THEN
INSERT
(ElevationID
,FloorName
,FloorDescription)
VALUES
(Src.ElevationID
,Src.FloorName
,Src.FloorDescription)
OUTPUT
Src.FloorID AS OldFloorID
,inserted.FloorID AS NewFloorID
INTO @MapFloors(OldFloorID, NewFloorID)
;
之间的映射复制Panels
。
这是最后一级的细节,因此我们可以使用简单的FloorID
而不是
记住INSERT
。
IDs