如何在数据具有层次结构时创建数据副本

时间:2016-04-26 21:22:50

标签: sql-server

我有一个表结构,子表中有FK列。

所以说有以下内容:

Company
-company_id
-name

Location
-location_id
-company_name
-name

Store
-store_id
-location_id
-name

Inventory
-inventory_id
-store_id

现在我想创建一个公司的副本,以及所有位置,商店和库存行。

所以说我要创建company_id = 123的副本,我必须复制所有行。

我试过了:

DECLARE @OriginalCompanyId = 123

DECALRE @companyId AS INT

INSERT Companies (name)
select c.name 
from companies c
where c.companyId = @OrignalCOmpanyId

SET @companyId = SCOPE_IDENTITY()

但是这种方法不起作用,因为其他表有多行,我不能连接新插入的PK值。

我应该采取什么方法?

1 个答案:

答案 0 :(得分:0)

我实际上一直在做一个这样做的项目。我的解决方案虽然不花哨,但到目前为止已证明有效..烦人的部分是设置过程。我对批评和改进建议持开放态度。

  1. 创建所有必要表格的“镜像”架构/ db(我已经使用New [ApplicationTableName])
  2. 对于每个pKey / fKey,创建一个“占位符”列(我已经使用p [ColumnName])
  3. 将现有数据映射到占位符键,索引为1.(这很烦人,但可以使用排名功能。)
  4. 按占位符键按降序插入应用程序(降序非常重要!)
  5. 使用排名功能更新您的“镜像”表(参见示例)
  6. 根据需要使用驱动/插入值重复所需的多个表格。
  7. 示例:

    鉴于此架构......

    CREATE TABLE Accounts (
        AccountID int identity(1,1) not null,
        Name varchar(500) not null
    
    )
    
    CREATE TABLE Users(
        UserID int identity(1,1) not null,
        AccountID int not null,
        Name varchar(500) not null
    )
    
    CREATE TABLE NewUsers(
        pUserID int not null,
        UserID int not null,
        AccountID int not null,
        Name varchar(500)
    )
    

    这个数据

    INSERT INTO NewUsers VALUES
    (1,0,0,'Bob'),
    (2,0,0,'Sally'),
    (3,0,0,'Jeff'),
    (4,0,0,'Sam')
    

    假设每次我们“创建”我们想要创建这4个默认用户的帐户......这看起来像这样

    DECLARE @AccountID int --this is scalar, so we'll use scope_identity() to grab it.
    INSERT INTO Account VALUES('MyNewAccountID')
    SELECT @AccountID = SCOPE_IDENTITY()
    
    --Prepare NewUsers w/ derived accountID
    UPDATE NewUsers SET AccountID = @AccountID
    
    --Do our "application" insert
    INSERT INTO Users(AccountID,Name)
    
    SELECT AccountID,Name
    FROM NewUsers
    ORDER BY pUserID DESC;
    
    --Capture inserted ID's for use in other tables (where we've derived pUserID)
    WITH InsertedUsers AS(
        SELECT
            --use dense rank, it handles fkey mappings too
            DENSE_RANK() OVER(ORDER BY UserID DESC) as pUserID,
            UserID
        FROM Users
    )
    UPDATE NewUsers SET UserID = iu.UserID
    FROM NewUsers nu
    JOIN InsertedUsers iu
    ON iu.pUserID = nu.pUserID
    
    
    SELECT TOP 100 * FROM Account ORDER BY 1 DESC
    SELECT TOP 100 * FROM Users ORDER BY 1 DESC
    

    现在,如果未来的表需要UserID进入应用程序(并且具有派生的pUserID),我们可以通过加入pUserID从NewUsers中获取它。