2012-06-27 31 views
11

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 MATCHEDNOT 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?

Trả lời

7

Vì vậy, tập hợp kết quả của bạn nên được

1 1 1 
2 1 0  
3 2 1 
4 1 1 

trong trường hợp này tuyên bố hợp nhất của bạn nên được

merge #target as t 
using #source as source 
on (t.id=source.id) 
when matched then update set isactive=1 
when not matched by target then insert values (id, @sourceid,1) 
when not matched by source and [email protected] then update set isactive=0 

Full kiểm tra:

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 
select @SourceId = 1;  

merge #target as t 
using #source as source 
on (t.id=source.id) 
when matched then update set isactive=1 
when not matched by target then insert values (id, @sourceid,1) 
when not matched by source and [email protected] then update set isactive=0; 


SELECT * FROM #target 

drop table #target; 
drop table #source 

kết quả ...

Id   SourceId IsActive 
----------- ----------- -------- 
1   1   1 
2   1   0 
3   2   1 
4   1   1 
+0

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. –

+1

@KirkBroadhurst Nó không dành cho tôi! Xem bài kiểm tra đầy đủ ở trên – podiluska

+0

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 đó. –

Các vấn đề liên quan