当前位置: 首页 > 面试题库 >

级联复制包含所有子行及其子行等的行

楚修为
2023-03-14
问题内容

我正在尝试跟踪商业建筑的项目(特别是混凝土覆层)。

  • 一个项目可以有多个街区(一个街区是一个独立的建筑物)
  • 一个街区可以有多个高程(建筑面;北,东等)
  • 海拔高度可以有多个楼层(高层建筑)
  • 地板可以有许多面板(面板是混凝土外墙的一部分)

为了使在数据库中构建面板时可以更轻松地进行跟踪,我希望能够复制一个块(由于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

如果我复制一个块,则需要

  1. 复制当前块,但用户应该能够选择Blocks.name。
  2. 复制该街区上的所有高程
  3. 复制每个海拔上的所有楼层
  4. 复制每个楼层的所有面板

让我知道您是否还需要其他任何信息,谢谢您的提前帮助!

我的尝试(经过先前的建议)

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,因此它没有要复制的内容,因为它们尚不存在),但我不知道如何解决。


问题答案:

我认为Blocks.BlockIDElevations.ElevationIDFloors.FloorIDPanels.PanelID是主键和自动生成的IDENTITY

  • 一个Block有很多Elevations
  • 一个Elevation有很多Floors
  • 一个Floor有很多Panels

我会用MERGEwithOUTPUT子句。

MERGE可以INSERTUPDATEDELETE行。在这种情况下,我们只需要INSERT

1=0始终为假,因此NOT MATCHED BY TARGET始终执行该部分。通常,可能还有其他分支,请参阅文档。 WHEN MATCHED通常用于UPDATE; WHEN NOT MATCHED BY SOURCE通常用于DELETE,但是我们在这里不需要它们。

这种复杂的形式MERGE等效于simple
INSERT,但与simple不同,INSERT它的OUTPUT子句允许引用我们需要的列。它允许从源表和目标表中检索列,从而节省了旧的现有ID和由生成的新ID之间的映射IDENTITY

堵塞

复制给定的一个,Block并记住ID新的Block。我们可以在此处使用simpleINSERTSCOPE_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

INSERT INTO Panels
    (FloorID
    ,PanelName
    ,PanelDescription)
SELECT
    M.NewFloorID
    ,Panels.PanelName
    ,Panels.PanelDescription
FROM
    Panels
    INNER JOIN Floors ON Floors.FloorID = Panels.FloorID
    INNER JOIN Elevations ON Elevations.ElevationID = Floors.ElevationID
    INNER JOIN @MapFloors AS M ON M.OldFloorID = Floors.FloorID
WHERE Elevations.BlockID = @blockToCopy
;


 类似资料:
  • 我正在编写一个查询来选择所有行,其中所有子行只包含相同的值,而不包含其他场景。 尝试了很多网上的例子,没有匹配。 从所有子级仅包含相同值而没有其他方案的表中选择*。必须包含至少一个要返回的子级。 子级通过ID映射到父级。 子值为一列,可以为int或null。假设所有子级必须包含值5,而不包含任何其他值。如果大多数子级都包含5,则将不起作用,则必须是所有子级都只有5的家长。 父级可能有多个子级 父级

  • 所以我和蛇怪打过交道。我知道如何使用返回字符串和对象的hashmap。为了演示,我有一个包含值的yaml文件: 当我使用

  • 我们正在使用谷歌的Firestore获取嵌入式机器配置数据。因为这些数据控制着一个可配置的页面流和许多其他东西,所以它被分割成许多子集合。在这个系统中,每台机器都有自己的顶级文档。然而,当我们向机队中添加机器时,需要花费很长时间,因为我们必须手动复制多个文档中的所有数据。有人知道如何在Python中递归复制Firestore文档、所有的子集合、它们的文档、子集合等吗。您将有一个顶级文档的引用,以及

  • 问题内容: 考虑数据库中的以下行: 每个具有的 是“所有者” /“超级父代”。 从表现的角度来看,收集父母和子女的最佳方法是什么?我应该使用 LINQ 还是 存储过程 ? 我希望最终结果是。 问题答案: 在SQL中,您可以使用CTE进行查询。例如,要检索在其树中具有其父级和最高父级的节点的列表: 这给出了: 请注意,我更改了示例数据,因此第2行不再是其自身的子级,而是第1行的子级。

  • 引用 Assoc.nsh 的内容: /**************************** 文件关联 NSIS 实用函数(修正) By:Ansifa 修正:2008年2月15日 *修正了关联错误(发布太急了,没发现,惭愧). 就是将下面代码改好了.大家自己找找改了什么:p WriteRegStr HKCR "${Project}.${type}" "" "${desc}" W

  • 如何选择以下条件: 选择不带子项的所有父项 选择所有父级和子级 选择带有雄性子项的所有父项(因此,当通过groovy类型转换转换为JSON时,只应包括雄性子项) 我不知道如何开始编码1和2,也许与有关--我真的不知道。虽然我在第3章的想法是: 但问题是,当转换为JSON时,它包含了非男性条目。有谁能帮我解决问题吗?使用会很好,但也可以在中使用。