使用t-sql迁移数据时维护外键引用

时间:2013-06-19 22:11:27

标签: sql-server tsql foreign-keys

我有3张桌子。

1)SourceTable - 包含一些数据的源表

2)DestinationTable - 与Source表具有相同模式的目标表。两个表都有类似的数据

3)FKSourceTable - 一个完全不同的表,其中包含对SourceTable的FK引用

4)FKDestinationTable - 一个完全不同的表,它具有对DestinationTable的FK引用。与FKSourceTable具有相同的架构

现在我的任务是将部分数据从SourceTable迁移到DestinationTable,将FKSourceTable迁移到FKDestinationTable

但是我无法迁移主键,因为DestinationTable可能有自己的记录具有相同的PK并且可能会造成PK违规。

DestinationTable作为PK的自动标识列,当我执行批量插入时,我没有指定PK列,因此自动标识将执行其作业。

这意味着DestionationTable中的新记录将具有全新的ID。

我遇到的问题是,在将FKSourceTable迁移到FKDestinationTable时,如何维护FK参考?当我按如下方式对DestinationTable进行批量插入时,我忘记了身份:

INSERT INTO DestionationTable
    (Col1, Col2)
SELECT st.Col1, st.Col2
FROM SourceTable st

(DestionationTable有3列:Id,Col1,Col2)

挑战在于我不能使用SSIS或任何其他ETL解决方案。我需要能够使用简单的SQL脚本执行此操作。

有没有人有任何想法来解决这个问题?我尝试过使用OUTPUT INTO等,但我还没想出一种方法来保持原始Id和新Id之间的引用

非常感谢任何帮助

谢谢 Nandun。

2 个答案:

答案 0 :(得分:3)

这可能不是最佳解决方案,但它应该完成工作。

想法是禁用身份插入并根据表中已有的内容自行生成ID。

这样做是迭代源数据并一次一行地将其插入到目标表中。

请在执行前仔细阅读此代码,因为我自己没有对此进行测试

declare @col1 varchar(20)
declare @col2 varchar(20)
declare @col3 varchar(20)
declare @new_id int

set identity_insert on

declare source_data cursor for
select col1, col2, colx
from SourceTable

open source_data

fetch next from source_data 
into @col1, @col2, @col3

WHILE @@FETCH_STATUS = 0
begin
  set @new_id = select MAX(ID) + 1 from SourceTable

insert into DestinationTable (ID, col1, col2, col3) values (@new_id,@col1,@col2,@col3)
-- do something similar for FKDestinationTable
insert into FKDestinationTable (ID, col1, col2, col3) values (@new_id,@col1,@col2,@col3)

fetch next from source_data
into @col1, @col2, @col3 
end 

set identity_insert off

答案 1 :(得分:0)

使用Destination表的Ident_Current

将数据插入Destination表
    DECLARE @ID  INT = IDENT_CURRENT('DestionationTable')

    INSERT INTO DestionationTable
        (ID, Col1, Col2)
    SELECT @ID + ROW_NUMBER() OVER(ORDER BY st.ID),st.Col1, st.Col2
    FROM SourceTable st
    WHERE -----

现在您可以获得源表中每个ID =目标表中的哪个ID的信息。

    SELECT @ID + ROW_NUMBER() OVER(ORDER BY st.ID) [NEW_ID], st.ID [OLD_ID]
    FROM SourceTable st
    WHERE -----

注意:确保在事务中完成此操作,事务类型取决于这些表的用法