2010-03-19 27 views
53

Tôi đang cố gắng thực hiện chèn/cập nhật hàng đơn trên một bảng nhưng tất cả các ví dụ hiện có cho bộ.cho hàng đơn MERGE/upsert trong SQL Server

bất cứ ai có thể sửa chữa cú pháp của tôi xin vui lòng:

MERGE member_topic ON mt_member = 0 AND mt_topic = 110 
WHEN MATCHED THEN UPDATE SET mt_notes = 'test' 
WHEN NOT MATCHED THEN INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test') 

Nghị quyết mỗi marc_s là để chuyển đổi hàng duy nhất để một subquery - mà làm cho tôi nghĩ rằng lệnh MERGE là không thực sự dành cho upserts hàng duy nhất.

MERGE member_topic 
USING (SELECT 0 mt_member, 110 mt_topic) as source 
ON member_topic.mt_member = source.mt_member AND member_topic.mt_topic = source.mt_topic 
WHEN MATCHED THEN UPDATE SET mt_notes = 'test' 
WHEN NOT MATCHED THEN INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test'); 
+0

Hmm , các dòng được đặt cách nhau rất gần trong trình duyệt của tôi mà một số dấu gạch dưới không hiển thị. – Jacob

Trả lời

42

Về cơ bản, bạn đang đi đúng hướng - nhưng bạn đang bỏ lỡ một nguồn từ nơi mà bạn muốn kết hợp các dữ liệu - hãy thử một cái gì đó như thế này:

MERGE 
    member_topic AS target 
USING 
    someOtherTable AS source 
ON 
    target.mt_member = source.mt_member 
    AND source.mt_member = 0 
    AND source.mt_topic = 110 
WHEN MATCHED THEN 
    UPDATE SET mt_notes = 'test' 
WHEN NOT MATCHED THEN 
    INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test') 
; 

Không có cú pháp đặc biệt cho một hàng MERGE - tất cả những gì bạn cần làm là sử dụng một mệnh đề thích hợp. Với điều kiện thích hợp trong mệnh đề ON, bạn có thể giới hạn nguồn thành một hàng duy nhất - không vấn đề gì.

Và đừng quên dấu chấm phẩy sau! Không đùa - điều quan trọng!

Xem this blog post để có phần giới thiệu thực sự tốt cho MERGE.

+6

Tôi không có một someOtherTable. Bạn đang nói tôi phải mô phỏng một cái gì đó như thế này? SỬ DỤNG (CHỌN 0 mt_member, 110 mt_topic) là nguồn – Jacob

+0

@Jacob: bạn phải có nguồn, vâng - một truy vấn phụ như bạn đề cập nên ổn - hãy thử! –

+5

Đối với bất kỳ ai nhầm lẫn với câu trả lời này, hãy xem [câu hỏi khác này] (http://stackoverflow.com/questions/11216067/what-is-using-in-sql-server-2008-merge-syntax). –

88

cuối cùng tôi đã nhận cú pháp Upsert sử dụng MERGE trong SQL Server 2008. Sử dụng những gì Jacob muốn làm (một Upsert):

IF EXISTS(SELECT * FROM member_topic WHERE mt_member = 0 AND mt_topic = 110) 
BEGIN 
    --update existing row 
    UPDATE member_topic SET mt_notes = 'test' 
    WHERE mt_member = 0 
    AND mt_topic = 110 
END 
ELSE 
BEGIN 
    --insert new row 
    INSERT INTO member_topic (mt_member, mt_topic, mt_notes) 
    VALUES (0, 110, 'test') 
END 

Tương đương MERGE Cú pháp là:

MERGE member_topic 
USING ( 
    VALUES (0, 110, 'test') 
) AS foo (mt_member, mt_topic, mt_notes) 
ON member_topic.mt_member = foo.mt_member 
    AND member_topic.mt_topic = foo.mt_topic 
WHEN MATCHED THEN 
    UPDATE SET mt_notes = foo.mt_notes 
WHEN NOT MATCHED THEN 
    INSERT (mt_member, mt_topic, mt_notes) 
    VALUES (foo.mt_member, foo.mt_topic, foo.mt_notes) 
; --A MERGE statement must be terminated by a semi-colon (;). 
+8

Trong mệnh đề 'WHEN NOT MATCHED THEN', tại sao bạn chèn' VALUES (mt_member, mt_topic, mt_notes) 'và không phải' VALUES (foo.mt_member, foo.mt_topic, foo.mt_notes) '? –

+0

@SamP Vì sao không? Có phải như SQL Server sẽ lấy các giá trị từ một nơi nào đó * khác * so với bảng giả 'foo'? Oh wait ... –

+0

Sẽ không phải dòng "UPDATE member_topic SET mt_notes = 'test'" trong bản cập nhật ví dụ không hợp nhất _all_ hàng trong bảng? Không phải là những gì được dự định. –

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