我有3个彼此相互关联的表。表格的设计如下。
我试图将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。
可能的解决方案
重用旧的First.FirstID 我想到的一个解决方案是使用重用数据库A中的旧First.FirstID。可以通过设置SET IDENTITY_INSERT TableName ON
来完成就在insert into TableName
之前,并将TableName.TableNameID
包含在insert语句中。但是,我建议我不要这样做。
使用新的First.FirstID覆盖Second.FirstID,然后使用新的Second.SecondID 覆盖Third.SecondID我试图使用OUTPUT
来应用此解决方案和TABLE
变量通过将所有First.FirstID输出到临时表变量并将它们与表第二similar to this answer相关联但是,我坚持如何将Second.FirstID与正确关联和替换临时表中的ID。关于如何做到这一点的答案也将被接受为此问题的答案。
使用解决方案1并使用UPDATE CASCADE
更新主键和外键。我刚刚得到了这个想法,但我觉得这将是非常乏味的。需要做更多的研究,但如果有一个答案显示如何成功实施,那么我将接受这个答案。
那么如何将3个相互关联的表中的记录复制到另外3个相似的表但不同的主键?有没有比上面提出的解决方案更好的解决方案?
答案 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