CHÈN VÀO… CHỌN TỪ… TRÊN CẬP NHẬT KHÓA DUPLICATE


116

Tôi đang thực hiện một truy vấn chèn trong đó hầu hết nhiều cột sẽ cần được cập nhật các giá trị mới nếu một khóa duy nhất đã tồn tại. Nó đi một cái gì đó như thế này:

INSERT INTO lee(exp_id, created_by, 
                location, animal, 
                starttime, endtime, entct, 
                inact, inadur, inadist, 
                smlct, smldur, smldist, 
                larct, lardur, lardist, 
                emptyct, emptydur)
SELECT id, uid, t.location, t.animal, t.starttime, t.endtime, t.entct, 
       t.inact, t.inadur, t.inadist, 
       t.smlct, t.smldur, t.smldist, 
       t.larct, t.lardur, t.lardist, 
       t.emptyct, t.emptydur 
FROM tmp t WHERE uid=x
ON DUPLICATE KEY UPDATE ...; 
//update all fields to values from SELECT, 
//       except for exp_id, created_by, location, animal, 
//       starttime, endtime

Tôi không chắc cú pháp của UPDATEmệnh đề phải là gì. Làm cách nào để tham chiếu đến hàng hiện tại từ SELECTmệnh đề?

Câu trả lời:


172

MySQL sẽ giả sử phần trước dấu bằng tham chiếu đến các cột có tên trong mệnh đề INSERT INTO và phần thứ hai tham chiếu đến các cột CHỌN.

INSERT INTO lee(exp_id, created_by, location, animal, starttime, endtime, entct, 
                inact, inadur, inadist, 
                smlct, smldur, smldist, 
                larct, lardur, lardist, 
                emptyct, emptydur)
SELECT id, uid, t.location, t.animal, t.starttime, t.endtime, t.entct, 
       t.inact, t.inadur, t.inadist, 
       t.smlct, t.smldur, t.smldist, 
       t.larct, t.lardur, t.lardist, 
       t.emptyct, t.emptydur 
FROM tmp t WHERE uid=x
ON DUPLICATE KEY UPDATE entct=t.entct, inact=t.inact, ...

6
@dnagirl: MẸO: đừng cố cập nhật bất kỳ cột nào trong số các cột PK, chỉ những cột cần cập nhật mới được đưa vào danh sách
lexu

45
Cú pháp đề xuất của bạn hoạt động và t.là bắt buộc. Tôi cũng tìm thấy một bài viết về xaprb ( xaprb.com/blog/2006/02/21/flexible-insert-and-update-in-mysql ) có sử dụng cú pháp sau: on duplicate key update b = values(b), c = values(c). Điều này cũng hoạt động.
dnagirl

9
Lưu ý: Điều này sẽ không hoạt động khi SELECT tuyên bố có một mệnh đề GROUP BY
John

11
@john Phải làm gì nếu câu lệnh SELECT có mệnh đề GROUP BY
Kathir

2
dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html cho biết `trong MySQL 5.6.4 trở lên, INSERT ... CHỌN TRÊN DUPLICATE KEY UPDATE câu lệnh được gắn cờ là không an toàn cho sao chép dựa trên câu lệnh ... Bên cạnh đó, bắt đầu với MySQL 5.6.6, một INSERT ... ON DUPLICATE kEY CẬP NHẬT tuyên bố chống lại một bảng có nhiều hơn một khóa duy nhất hoặc chính cũng được đánh dấu là unsafe.`
Abdul Muneer

51

Mặc dù tôi đã rất muộn để làm điều này nhưng sau khi thấy một số câu hỏi hợp pháp cho những người muốn sử dụng INSERT-SELECTtruy vấn với GROUP BYmệnh đề, tôi đã nghĩ ra công việc xung quanh cho việc này.

Tiếp tục câu trả lời của Marcus Adams và tính toán GROUP BYtrong đó, đây là cách tôi sẽ giải quyết vấn đề bằng cách sử dụngSubqueries in the FROM Clause

INSERT INTO lee(exp_id, created_by, location, animal, starttime, endtime, entct, 
                inact, inadur, inadist, 
                smlct, smldur, smldist, 
                larct, lardur, lardist, 
                emptyct, emptydur)
SELECT sb.id, uid, sb.location, sb.animal, sb.starttime, sb.endtime, sb.entct, 
       sb.inact, sb.inadur, sb.inadist, 
       sb.smlct, sb.smldur, sb.smldist, 
       sb.larct, sb.lardur, sb.lardist, 
       sb.emptyct, sb.emptydur
FROM
(SELECT id, uid, location, animal, starttime, endtime, entct, 
       inact, inadur, inadist, 
       smlct, smldur, smldist, 
       larct, lardur, lardist, 
       emptyct, emptydur 
FROM tmp WHERE uid=x
GROUP BY location) as sb
ON DUPLICATE KEY UPDATE entct=sb.entct, inact=sb.inact, ...

8
Đây là câu trả lời phù hợp cho các truy vấn với COUNT, GROUP, v.v. Cảm ơn.
Kostanos

Cảm ơn bạn rất nhiều, dude! Tôi thực sự thích cách tiếp cận này, đặc biệt vì nó cho phép tôi tạo một cơ chế giống như Truy vấn liên tục, một thứ mà InfluxDB's làm.
Miere

1
Bạn cũng có thể sử dụng trường = VALUES (trường) trong bản cập nhật trùng lặp như trong câu trả lời trong stackoverflow.com/questions/16935896/…
Erik Melkersson 16/09/18
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.