Tôi có một bảng mục tiêu chứa một mục có cờ IsActive
và tôi đang chèn và cập nhật từ một bảng nguồn bằng cách sử dụng câu lệnh MERGE
. Nếu một cái gì đó tồn tại trong bảng nguồn thì nó hoạt động, và nếu nó không thì nó không hoạt động. Logic là khá đơn giản:Tôi có thể áp dụng mệnh đề WHERE trên mục tiêu trong tuyên bố MERGE không?
- nếu nó tồn tại trong nguồn và mục tiêu hàng nên có
IsActive
đúng - nếu nó chỉ tồn tại trong nguồn sau đó một hàng mới nên được chèn vào mục tiêu, với
IsActive
đúng - nếu chỉ tồn tại trong mục tiêu thì
IsActive
phải được đặt thành false.
Tất cả rất đơn giản, ngoại trừ bảng đích cũng có cột phân biệt SourceId
liên quan đến bảng nguồn. Vì vậy, đối với một bảng nguồn đã cho, tôi chỉ muốn MERGE
đối với các hàng có SourceId
tương ứng.
(bảng bình thường của tôi chứa hàng của các kiểu dữ liệu giống hệt nhau từ nhiều hệ thống - Tôi lấy dữ liệu từ các hệ thống độc lập và do đó cần phải sáp nhập từ một nguồn ở một thời điểm)
Dưới đây là một ví dụ:
IF OBJECT_ID('tempdb..#target') IS NOT NULL DROP TABLE #target
IF OBJECT_ID('tempdb..#source') IS NOT NULL DROP TABLE #source
CREATE TABLE #target (Id INT, SourceId INT, IsActive BIT)
INSERT #target VALUES (1, 1, 0)
INSERT #target VALUES (2, 1, 1)
INSERT #target VALUES (3, 2, 1)
CREATE TABLE #source (Id INT)
INSERT #source VALUES (1)
INSERT #source VALUES (4)
DECLARE @SourceId INT = 1;
SELECT * FROM #target
MERGE INTO #target t
USING
(
SELECT [Id] FROM #source
) AS s
ON t.[Id] = s.[Id] AND t.[SourceId] = @SourceId
WHEN MATCHED THEN UPDATE SET [IsActive] = 1
WHEN NOT MATCHED BY TARGET THEN INSERT VALUES ([Id], @SourceId, 1)
WHEN NOT MATCHED BY SOURCE THEN UPDATE SET [IsActive] = 0;
SELECT * FROM #target
Nỗ lực ban đầu của tôi là bao gồm AND t.[SourceId] = @SourceId
trong điều kiện hợp nhất, nhưng rõ ràng điều đó sẽ không hoạt động - nó hạn chế các mục hợp nhất chứ không phải là bảng mục tiêu. ID mục tiêu = 3 sẽ không khớp và do đó, nó sẽ được đặt thành không hoạt động, cho dù điều kiện bổ sung đó có được bao gồm hay không.
Kết quả cuối cùng là bất cứ khi nào quy trình được chạy cho hệ thống nguồn, tất cả các hệ thống khác sẽ được đặt thành không hoạt động.
Giải pháp của tôi cho đến nay là để chạy các MERGE
chỉ cho MATCHED
và NOT MATCHED BY TARGET
, và sau đó chạy một tiếp theo UPDATE
cho các hàng chưa từng có
UPDATE #target
SET [IsEnabled] = 0
WHERE [SourceId] = @SourceId
AND [ID] NOT IN (SELECT [ID] FROM #source)
Có cách nào để bao gồm điều kiện lọc này trong báo cáo MERGE
? Có cách thông minh nào khác để đạt được điều này không?
Nếu bạn thử, bạn sẽ thấy rằng nó cung cấp '3 2 0' cho hàng được đề cập. Lý do là khi bạn tham gia vào 't.id = source.id', không có' t' cho hàng 3. Nó được xử lý giống như hàng 2 và được đánh dấu là đang hoạt động. –
@KirkBroadhurst Nó không dành cho tôi! Xem bài kiểm tra đầy đủ ở trên – podiluska
Tôi hiểu rồi, tôi đã quá nhanh để đọc. Cảm ơn câu trả lời tuyệt vời! Tôi không biết tôi có thể đặt một điều kiện trong đó. –