2009-07-29 38 views
43

Trong MySQL, nếu bạn chỉ định ON DUPLICATE KEY UPDATE và một hàng được chèn vào sẽ gây ra một giá trị trùng lặp trong chỉ mục UNIQUE hoặc PRIMARY KEY, một UPDATE của hàng cũ được thực hiện. Ví dụ: nếu cột a được khai báo là UNIQUE và chứa giá trị 1, hai câu sau có hiệu lực giống hệt nhau:Liệu SQL Server có cung cấp bất cứ thứ gì giống như việc cập nhật KEY DUPLICATE của MySQL

INSERT INTO table (a,b,c) VALUES (1,2,3) 
    ON DUPLICATE KEY UPDATE c=c+1; 

UPDATE table SET c=c+1 WHERE a=1; 

Tôi không tin rằng tôi đã gặp bất kỳ thứ gì giống như trong T-SQL. SQL Server có cung cấp bất kỳ thứ gì có thể so sánh được với UPDATE DUPLICATE KEY của MySQL không?

+0

Bạn có thể mô phỏng nó bằng quy trình được lưu trữ. Tôi không có mã chính xác trên đầu của tôi. –

+0

@Robert Harvey - Tôi luôn thực hiện thao tác bằng cách kiểm tra xem hàng có tồn tại không. Nếu có, sau đó thực hiện cập nhật khác chèn một hàng mới. Đó là những gì bạn đang suy nghĩ là tốt? –

Trả lời

35

Không có DUPLICATE KEY CẬP NHẬT tương đương, nhưng MERGE và khi xuất hiện có thể làm việc cho bạn

Inserting, Updating, and Deleting Data by Using MERGE

+11

Chỉ cần lưu ý rằng MERGE không được miễn nhiễm với va chạm chèn đồng thời cao. Bạn ** phải ** sử dụng WITH (UPDLOCK, HOLDLOCK) để hợp nhất để không va chạm. Một số hệ thống siêu giao dịch mỗi giây sử dụng một chiến lược khác nơi ổ khóa không được sử dụng, nhưng bất kỳ lỗi nào đều bị mắc kẹt và sau đó được chuyển đổi thành bản cập nhật. – ErikE

+3

tên người dùng này xứng đáng được nhiều phiếu bầu hơn. – Pete

2

SQL Server 2008 có tính năng này, như một phần của TSQL.
Xem tài liệu về tuyên bố MERGE tại đây - http://msdn.microsoft.com/en-us/library/bb510625.aspx

+1

Chỉ cần lưu ý rằng MERGE không được miễn nhiễm với va chạm chèn đồng thời cao. Bạn phải sử dụng WITH (UPDLOCK, HOLDLOCK) để hợp nhất để không va chạm. Một số hệ thống siêu giao dịch mỗi giây sử dụng một chiến lược khác nơi ổ khóa không được sử dụng, nhưng bất kỳ lỗi nào đều bị mắc kẹt và sau đó được chuyển đổi thành bản cập nhật. – ErikE

16

Tôi ngạc nhiên rằng không ai trong số các câu trả lời trên trang này chứa một ví dụ về truy vấn thực tế, vì vậy ở đây bạn đi:

Một ví dụ phức tạp hơn chèn dữ liệu và sau đó xử lý lặp lại

MERGE 
INTO MyBigDB.dbo.METER_DATA WITH (HOLDLOCK) AS target 
USING (SELECT 
    77748 AS rtu_id 
    ,'12B096876' AS meter_id 
    ,56112 AS meter_reading 
    ,'20150602 00:20:11' AS local_time) AS source 
(rtu_id, meter_id, meter_reading, time_local) 
ON (target.rtu_id = source.rtu_id 
    AND target.time_local = source.time_local) 
WHEN MATCHED 
    THEN UPDATE 
     SET meter_id = '12B096876' 
     ,meter_reading = 56112 
WHEN NOT MATCHED 
    THEN INSERT (rtu_id, meter_id, meter_reading, time_local) 
     VALUES (77748, '12B096876', 56112, '20150602 00:20:11'); 
+4

Bạn thưa ... là một người tiết kiệm cuộc sống. Tôi thực sự ghét các tài liệu microsoft ... họ luôn luôn cung cấp cho tất cả các ví dụ ngoại trừ những được sử dụng thường xuyên nhất – Tschallacka

+0

' 'MERGE VÀO MyFancyTableName VỚI (HOLDLOCK) AS mục tiêu \t \t \t SỬ DỤNG \t \t \t (SELECT: id AS id, : lastaccess AS lastaccess) AS nguồn \t \t \t (id, lastaccess) \t \t \t ON \t \t \t (target.id = nguồn.id) \t \t \t khi xuất hiện sau đó cập nhật SET lastaccess =: lastaccess2 \t \t \t KHI không phù hợp sau đó chèn (id, lastaccess) \t \t \t GIÁ TRỊ (: id2,: lastaccess3); ' 'Tôi có cần phải gửi cả biến trong 'USING' chọn hoặc chỉ là' id' là đủ ở đó? – Tschallacka

+0

Cảm ơn bạn đã tham khảo lệnh Merge. Tôi nên chỉ ra rằng trong các báo cáo MATCHED bạn đang sử dụng các giá trị giống như bạn đã định nghĩa là nguồn. Vì vậy, nếu bạn đang tìm kiếm một bản cập nhật của bản ghi, bạn nên gán giá trị nguồn như sau: –

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