Bạn có thể (ab) sử dụng MERGE
với OUTPUT
mệnh đề.
MERGE
có thể INSERT
, UPDATE
và DELETE
hàng. Trong trường hợp của chúng tôi, chúng tôi chỉ cần INSERT
.1 =0 luôn là false, vì vậy NOT MATCHED BY TARGET
một phần luôn được thực thi. Nói chung, có thể có các nhánh khác, hãy xem tài liệu. WHEN MATCHED
thường được sử dụng để UPDATE
; WHEN NOT MATCHED BY SOURCE
thường được sử dụng để DELETE
, nhưng chúng tôi không cần chúng ở đây.
Dạng phức tạp này của MERGE
tương đương với INSERT
đơn giản , nhưng không giống như INSERT
đơn giản OUTPUT
của nó mệnh đề cho phép tham chiếu đến các cột mà chúng ta cần. Nó cho phép truy xuất các cột từ cả bảng nguồn và bảng đích, do đó lưu ánh xạ giữa các ID cũ và mới.
MERGE INTO [dbo].[Test]
USING
(
SELECT [Data]
FROM @Old AS O
) AS Src
ON 1 = 0
WHEN NOT MATCHED BY TARGET THEN
INSERT ([Data])
VALUES (Src.[Data])
OUTPUT Src.ID AS OldID, inserted.ID AS NewID
INTO @New(ID, [OtherID])
;
Về bản cập nhật của bạn và dựa vào thứ tự của IDENTITY
đã tạo giá trị.
Trong trường hợp đơn giản, khi [dbo].[Test]
có IDENTITY
rồi đến INSERT
với ORDER BY
sẽ đảm bảo rằng IDENTITY
được tạo các giá trị sẽ theo thứ tự được chỉ định. Xem điểm 4 trong Đảm bảo đặt hàng trong SQL Server . Xin lưu ý bạn, nó không đảm bảo thứ tự vật lý của các hàng được chèn, nhưng nó đảm bảo thứ tự mà IDENTITY
các giá trị được tạo.
INSERT INTO [dbo].[Test] ([Data])
SELECT [Data]
FROM @Old
ORDER BY [RowID]
Tuy nhiên, khi bạn sử dụng OUTPUT
mệnh đề:
INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID] INTO @New
SELECT [Data]
FROM @Old
ORDER BY [RowID]
các hàng trong OUTPUT
luồng không có thứ tự. Ít nhất, nói đúng ra, ORDER BY
trong truy vấn áp dụng cho INSERT
chính hoạt động, nhưng không có gì ở đó cho biết thứ tự của OUTPUT
là gì . Vì vậy, tôi sẽ không cố gắng dựa vào đó. Sử dụng MERGE
hoặc thêm một cột bổ sung để lưu trữ ánh xạ giữa các ID một cách rõ ràng.