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

Sql 级联复制包含所有子行及其子行的行,等等,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我试图跟踪商业建筑施工中的项目(特别是混凝土覆层) 一个项目可以有多个街区(一个街区是一个独立的建筑) 一个块可以有多个立面(建筑面;北、东等) 立面可以有多个楼层(高层建筑) 地板可以有许多面板(面板是混凝土覆层的一部分) 为了使在数据库中构建面板时更容易,以便可以跟踪它们,我希望能够复制一个块(因为10次中有9次,每个块都是相同的,只是有一些小的更改) 就餐桌而言: 块 Blocks.BlockID, Blocks.BlockName, Blocks.BlockDescription

我试图跟踪商业建筑施工中的项目(特别是混凝土覆层)

  • 一个项目可以有多个街区(一个街区是一个独立的建筑)
  • 一个块可以有多个立面(建筑面;北、东等)
  • 立面可以有多个楼层(高层建筑)
  • 地板可以有许多面板(面板是混凝土覆层的一部分)
为了使在数据库中构建面板时更容易,以便可以跟踪它们,我希望能够复制一个块(因为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
高程

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
楼层

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
面板

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
如果我复制一个块,它需要

  • 复制当前块,但用户应该能够选择Blocks.name
  • 复制该块上的所有立面
  • 复制每个立面上的所有楼层
  • 复制每个楼层上的所有配电盘
  • 如果你还需要知道什么,请告诉我,谢谢你的帮助

    我的尝试(在先前的建议之后)


    在第二个层叠(尝试复制每个立面内的所有楼层)之后,会出现错误。我知道为什么会出错(我不是将原始ID与要复制到的新ID一起列出,而是自己输出新ID,这样它就没有什么可复制的了,因为它们还不存在),但我不知道如何修复它。

    我假设
    Blocks.BlockID
    Elevations.ElevationID
    floorrid
    Panels.PanelID
    是主键和自动生成的
    IDENTITY

    • 一个
      有许多
      立面
    • 一个
      立面
      有许多
      楼层
    • 一个
      楼层
      有许多
      面板
    我将使用with
    OUTPUT
    子句

    合并
    可以
    插入
    更新
    删除
    行。 在这种情况下,我们只需要插入

    1=0
    始终为false,因此始终执行目标不匹配的
    部分。
    一般来说,可能还有其他分支,请参见文档。
    
    匹配时
    通常用于
    更新
    当与源代码不匹配时
    通常用于
    删除
    ,但此处不需要它们

    这种复杂的
    合并
    形式相当于简单的
    插入
    , 但与简单的
    INSERT
    不同,它的
    OUTPUT
    子句允许引用我们需要的列。 它允许从源表和目标表中检索列,从而保存映射 在旧的现有ID和由
    IDENTITY
    生成的新ID之间

    复制一个给定的
    ,并记住新
    块的
    ID
    。 我们可以在这里使用简单的
    INSERT
    SCOPE\u 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();
    
    高程

    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
    
    从旧的
    复制
    立面
    ,并将其指定给新的
    。 还记得
    @MapElevations
    中旧
    ID
    和新生成的
    ID
    之间的映射吗

    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)
    ;
    
    楼层

    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
    
    使用新旧
    立面ID
    之间的映射复制
    楼层
    。 还记得
    @maplowers
    中旧
    ID
    和新生成的
    ID
    之间的映射吗

    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)
    ;
    
    面板

    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
    
    使用新旧
    floorrid
    之间的映射复制
    面板
    。 这是最后一级详细信息,因此我们可以使用simple
    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
    ;
    

    为什么需要复制立面图、配电盘和项目?新块不能仍然指向现有标高等,因此不是代码编写服务。当你陷入困境时,我们可以帮助你,但我们不会为你做你的工作。如果你试着写这篇文章,然后分享你尝试过的内容和部分,怎么样就前端而言,存储过程是最容易实现的,但以最简单的为准easiest@cloudsafe因为每个其他项目都必须构建和安装,所以每个项目都必须是唯一可识别的。@VladimirBaranov以前从未使用过merge。要想知道怎么做可不是件容易的事。有机会得到一些指导吗?:)妙极了!我为它添加了另一层,因此现在面板可以有许多“产品”(例如windows)。这一解释使得将面板合并/输出变得很容易,而新的最终层则是一个简单的插入!非常感谢!