如何将链接表中的记录复制到另一个数据库中的另一个表中?

时间:2016-07-11 10:13:14

标签: sql sql-server database sql-server-2008 tsql

我有3个彼此相互关联的表。表格的设计如下。

  • First(PK:FirstID,vchar:Name,int:Year)
  • 秒(PK:SecondID,FK:FirstID,int:Day,int:Month)
  • 第三名(PK:ThirdID,FK:SecondID,int:Speed,vchar:备注)

我试图将3个相互关联的表中的记录从数据库A复制到数据库B.所以我的Transact-SQL看起来像这样:

INSERT INTO First
(Name, Year)
SELECT  Name, Year
FROM    DB_A.dbo.First
WHERE Year >= 1992

INSERT INTO Second
(FirstID, Day, Month)
SELECT  FirstID, Day, Month
FROM    DB_A.dbo.Second S INNER JOIN
        DB_A.dbo.First F ON S.FirstID = F.FirstID
WHERE Month > 6

INSERT INTO Third
(SecondID, Speed, Remark)
SELECT  SecondID, Speed, Remark
FROM    DB_A.dbo.Third T INNER JOIN
        DB_A.dbo.Second S ON T.SecondID = S.SecondID INNER JOIN
        DB_A.dbo.First F ON F.FirstID = S.FirstID
WHERE Remark <> NULL

由于数据库B中的三个表为空,因此数据库A和B中的First.FirstID的起始位置变得不一样,这些语句一切正常。因此,产生了the constraint on foreign_key error

可能的解决方案

  1. 重用旧的First.FirstID 我想到的一个解决方案是使用重用数据库A中的旧First.FirstID。可以通过设置SET IDENTITY_INSERT TableName ON来完成就在insert into TableName之前,并将TableName.TableNameID包含在insert语句中。但是,我建议我不要这样做。

  2. 使用新的First.FirstID覆盖Second.FirstID,然后使用新的Second.SecondID 覆盖Third.SecondID我试图使用OUTPUT来应用此解决方案和TABLE变量通过将所有First.FirstID输出到临时表变量并将它们与表第二similar to this answer相关联但是,我坚持如何将Second.FirstID与正确关联和替换临时表中的ID。关于如何做到这一点的答案也将被接受为此问题的答案

  3. 使用解决方案1并使用UPDATE CASCADE更新主键和外键。我刚刚得到了这个想法,但我觉得这将是非常乏味的。需要做更多的研究,但如果有一个答案显示如何成功实施,那么我将接受这个答案。

  4. 那么如何将3个相互关联的表中的记录复制到另外3个相似的表但不同的主键?有没有比上面提出的解决方案更好的解决方案?

2 个答案:

答案 0 :(得分:0)

您可以使用OUTPUT Clause

CREATE TABLE #First (NewId INT PRIMARY KEY, OldId INT)  

INSERT INTO First
(
    Name, 
    Year,
    OldId -- Added new column 
)
OUTPUT Inserted.FirstID, Inserted.OldId INTO #First
SELECT  
    Name, 
    Year,
    FirstID -- Old Id to OldId Column
FROM    
    DB_A.dbo.First
WHERE 
    Year >= 1992

第二张表

CREATE TABLE #Second (NewId INT PRIMARY KEY, OldId INT) 
INSERT INTO Second
(
    FirstID, 
    Day, 
    Month,
    OldId -- Added new column 
)
OUTPUT Inserted.SecondID, Inserted.OldId INTO #Second
SELECT  
    OF.NewId, --FirstID
    Day, 
    Month,
    SecondID
FROM    
    DB_A.dbo.Second S INNER JOIN
    DB_A.dbo.First F ON S.FirstID = F.FirstID INNER JOIN
    #First OF ON F.FirstId = OF.OldId -- Old ids here
WHERE 
    Month > 6

最后一个

INSERT INTO Third
(
    SecondID,
    Speed,
    Remark
)
SELECT  
    OS.NewId, -- SecondID
    Speed, 
    Remark
FROM
    DB_A.dbo.Third T INNER JOIN
    DB_A.dbo.Second S ON T.SecondID = S.SecondID INNER JOIN
    DB_A.dbo.First F ON F.FirstID = S.FirstID INNER JOIN
    #Second  OS ON S.SecondID = OS.OldId 
WHERE Remark <> NULL

答案 1 :(得分:0)

第一个解决方案

Using MERGE and OUTPUT together

OUTPUT结合MERGE功能可以在插入表之前检索旧的主键。

第二个解决方案

注意:此解决方案仅在您确定除了表的主键之外还有另一列在表中具有唯一值的列时才有效。

您可以将此列用作源数据库中的表与目标数据库中的姐妹表之间的链接。下面的代码是一个示例,考虑到First.Name在月份&gt;时具有唯一值。 6。

-- no changes to insert code in First table
INSERT INTO First
(Name, Year)
SELECT  Name, Year
FROM    DB_A.dbo.First
WHERE Year >= 1992

INSERT INTO Second
(FirstID, Day, Month)
SELECT  CurrentF.FirstID, Day, Month -- 2. Use the FirstID that has been input in First table
FROM    DB_A.dbo.Second S INNER JOIN
        DB_A.dbo.First F ON S.FirstID = F.FirstID INNER JOIN
        First CurrentF ON CurrentF.Name = F.Name -- 1. Join Name as a link
WHERE Month > 6

INSERT INTO Third
(SecondID, Speed, Remark)
SELECT  CurrentS.SecondID, Speed, Remark --5. Get the proper SecondID
FROM    DB_A.dbo.Third T INNER JOIN
        DB_A.dbo.Second S ON T.SecondID = S.SecondID INNER JOIN
        DB_A.dbo.First F ON F.FirstID = S.FirstID INNER JOIN
        First CurrentF ON CurrentF.Name = F.Name INNER JOIN -- 3. Join using Name as Link
        Second CurrentS ON CurrentS.FirstID= CurrentF.FirstID -- 4. Link Second and First table to get the proper SecondID.
WHERE Remark <> NULL