Sql FKs链接的表中存在重复行
我试图通过复制数据库中的现有数据来生成一些用于测试的数据。有许多表由FKs链接,我希望保持相同的数据配置文件。我认为用一个例子来解释是最简单的: 客户编号 名称 年龄 1. 弗莱德 20 2. 上下快速移动 30 3. 乔 40Sql FKs链接的表中存在重复行,sql,sql-server,database,tsql,Sql,Sql Server,Database,Tsql,我试图通过复制数据库中的现有数据来生成一些用于测试的数据。有许多表由FKs链接,我希望保持相同的数据配置文件。我认为用一个例子来解释是最简单的: 客户编号 名称 年龄 1. 弗莱德 20 2. 上下快速移动 30 3. 乔 40 您可以使用OUTPUT子句: DECLARE @ids TABLE (customerid int, Name varchar(255), age int); INSERT INTO Customers (Name, Age) OUTPUT inserted.
您可以使用
OUTPUT
子句:
DECLARE @ids TABLE (customerid int, Name varchar(255), age int);
INSERT INTO Customers (Name, Age)
OUTPUT inserted.customerid, Name, Age INTO @ids
SELECT Name, Age
FROM Customers
WHERE Age > 18;
然后,您可以对其他表使用@ids
:
INSERT INTO invoices (CustomerID, Date)
SELECT cnew.customerID, i.date
FROM invoices i JOIN
customers c
ON i.customerID = c.customerID JOIN
@ids cnew
ON cnew.name = c.name AND cnew.age = c.age;
@id
s中的附加列是可用的,因此您可以将批处理与现有列相匹配。不幸的是,您不再具有id,因此希望其他一些列的组合能够唯一地标识原始客户。您可以使用MERGE
以及OUTPUT
子句来捕获新数据到旧数据的映射,例如
DECLARE @CustomerMapping TABLE (OldCustomerID INT NOT NULL, NewCustomerID INT NOT NULL);
MERGE Customers AS t
USING
( SELECT CustomerID, Name, Age
FROM Customers
WHERE Age > 18
) AS s
ON 1 = 0 -- THIS WILL NEVER BE TRUE SO WILL ALWAYS BE "NOT MATCHED"
WHEN NOT MATCHED THEN
INSERT (Name, Age)
VALUES (s.Name, s.Age)
OUTPUT s.CustomerID, inserted.CustomerID
INTO @CustomerMapping (OldCustomerID, NewCustomerID);
然后,您可以使用此ID映射对发票重复相同操作:
DECLARE @InvoiceMapping TABLE (OldInvoiceID INT NOT NULL, NewInvoiceID INT NOT NULL);
MERGE Invoices AS t
USING
( SELECT i.InvoiceID,
CustomerID = m.NewCustomerID,
i.Date
FROM Invoices AS i
INNER JOIN @CustomerMapping AS m
ON m.OldCustomerID = i.CustomerID
) AS s
ON 1 = 0
WHEN NOT MATCHED THEN
INSERT (CustomerID, Date)
VALUES (s.CustomerID, s.Date)
OUTPUT s.InvoiceID, inserted.InvoiceID
INTO @InvoiceMapping (OldInvoiceID, NewInvoiceID);
然后,您可以使用发票映射插入行项目:
INSERT LineItems (InvoiceID, Item, Price, Qty)
SELECT m.NewInvoceID,
li.Item,
li.Price,
li.Qty
FROM LineItems AS li
INNER JOIN @InvoiceMapping AS m
ON m.OldInvoiceID = li.InvoiceID;
由于不需要输出(除非行项有更多的子项,在这种情况下,您需要再次使用MERGE
并像以前一样捕获输出),因此标准的INSERT
将在此处执行
必须执行仅插入的伪合并
,以便捕获新ID和旧ID,使用正常的插入
,您只能访问输出
子句中插入的字段
由于bug的数量,在SQL Server中使用MERGE
总是有(合理的)顾虑,但是,只要您使用表作为目标并且只插入新数据,我所知道的bug都不会影响此场景
合并是这里缺少的一部分,我曾尝试使用输出来制作映射,但无法获得旧ID。谢谢!