MySql Table Insert nếu không tồn tại nếu không, hãy cập nhật


105
UPDATE AggregatedData SET datenum="734152.979166667", 
Timestamp="2010-01-14 23:30:00.000" WHERE datenum="734152.979166667";

Nó hoạt động nếu datenumtồn tại, nhưng tôi muốn chèn dữ liệu này dưới dạng một hàng mới nếu datenumkhông tồn tại.

CẬP NHẬT

datenum là duy nhất nhưng đó không phải là khóa chính


2
"Datenum" có phải là duy nhất không? Bạn có thể sử dụng INSERT ... ON DUPLICATE KEY UPDATE nếu có.
Jacob

Câu trả lời:


143

Jai là chính xác mà bạn nên sử dụng INSERT ... ON DUPLICATE KEY UPDATE.

Lưu ý rằng bạn không cần phải bao gồm dữ liệu trong mệnh đề cập nhật vì đó là khóa duy nhất, vì vậy nó không nên thay đổi. Bạn cần bao gồm tất cả các cột khác từ bảng của mình. Bạn có thể sử dụng VALUES()hàm để đảm bảo các giá trị thích hợp được sử dụng khi cập nhật các cột khác.

Đây là bản cập nhật của bạn được viết lại bằng INSERT ... ON DUPLICATE KEY UPDATEcú pháp thích hợp cho MySQL:

INSERT INTO AggregatedData (datenum,Timestamp)
VALUES ("734152.979166667","2010-01-14 23:30:00.000")
ON DUPLICATE KEY UPDATE 
  Timestamp=VALUES(Timestamp)

18
Hãy cẩn thận khi sử dụng INSERT ... ON DUPLICATE KEY UPDATE trên các bảng so với một bảng có nhiều hơn một khóa duy nhất hoặc chính. Lấy từ tài liệu MySQL : Ngoài ra, bắt đầu bằng MySQL 5.5.24, một câu lệnh INSERT ... ON DUPLICATE KEY UPDATE chống lại một bảng có nhiều hơn một khóa duy nhất hoặc khóa chính cũng được đánh dấu là không an toàn. (Lỗi # 11765650, Lỗi # 58637) Mô tả lỗi 58637 bug.mysql.com/bug.php?id=58637
băng thông rộng

1
Nó có thể là cần thiết để tạo ra UNIQUEkhó khăn cho Timestampbằng cách sử dụngALTER TABLE AggregatedData ADD UNIQUE (Timestamp)
Avyakt

@broadband bạn có thể sử dụng một chìa khóa hợp để tránh lỗi này
Kareem

16

Hãy thử sử dụng cái này :

Nếu bạn chỉ định ON DUPLICATE KEY UPDATEvà một hàng được chèn sẽ gây ra giá trị trùng lặp trong CẬP NHẬT TỪ UNIQUE index orKHÓA , MySQL performs an [CHÍNH`] ( http://dev.mysql.com/doc/refman/5.7/en/update.html ) của hàng cũ. ..

Các ON DUPLICATE KEY UPDATEđiều khoản có thể chứa nhiều bài tập cột, cách nhau bằng dấu phẩy.

Với ON DUPLICATE KEY UPDATE, giá trị hàng bị ảnh hưởng trên mỗi hàng là 1 nếu hàng được chèn dưới dạng hàng mới, 2 nếu hàng hiện có được cập nhật và 0 nếu hàng hiện có được đặt thành giá trị hiện tại. Nếu bạn chỉ định CLIENT_FOUND_ROWScờ mysql_real_connect()khi kết nối với mysqld , giá trị hàng bị ảnh hưởng là 1 (không phải 0) nếu một hàng hiện có được đặt thành giá trị hiện tại của nó ...


Nhưng dữ liệu của tôi không phải là khóa chính.
OHLÁLÁ

Vì vậy, trong trường hợp của tôi giải pháp là gì, tôi đã thử giải pháp này, mà không có bất kỳ giải pháp nào: CHÈN VÀO forwind.aggregateddata (datenum, Timestamp, Min_F1_baro_20_) VALUES ('1', '2', '3') ON DUPLICATE KEY UPDATE datenum = datenum;
OHLÁLÁ

1
datenum có phải là duy nhất không? nếu có, hơn là thêm một chỉ mục duy nhất vào nó (nếu chưa được thêm) Sau đó nó sẽ hoạt động. Tham khảo dev.mysql.com/doc/refman/5.1/en/alter-table.html để biết cách quảng cáo các chỉ mục DUY NHẤT
Jai

bây giờ tôi đã xác định dữ liệu là duy nhất và nó hoạt động tốt, cảm ơn
OHLÁLÁ

1
Chỉ là một liên kết, có thể đưa ra câu trả lời.
Andrew

0

Tôi đã gặp trường hợp cần cập nhật hoặc chèn vào bảng theo hai trường (cả hai khóa ngoại) mà tôi không thể đặt ràng buộc DUY NHẤT (vì vậy CHÈN ... TRÊN CẬP NHẬT KHÓA DUPLICATE sẽ không hoạt động). Đây là những gì tôi đã sử dụng:

replace into last_recogs (id, hasher_id, hash_id, last_recog) 
  select l.* from 
    (select id, hasher_id, hash_id, [new_value] from last_recogs 
     where hasher_id in (select id from hashers where name=[hasher_name])
     and hash_id in (select id from hashes where name=[hash_name]) 
     union 
     select 0, m.id, h.id, [new_value] 
     from hashers m cross join hashes h 
     where m.name=[hasher_name] 
     and h.name=[hash_name]) l 
  limit 1;

Ví dụ này được lấy từ một trong các cơ sở dữ liệu của tôi, với các tham số đầu vào (hai tên và một số) được thay thế bằng [hasher_name], [hash_name] và [new_value]. SELECT ... LIMIT 1 lồng nhau kéo bản ghi đầu tiên của bản ghi hiện có hoặc bản ghi mới (last_recogs.id là khóa chính tự động gia tăng) và sử dụng nó làm giá trị đầu vào cho REPLACE INTO.


REPLACE luôn chèn một hàng mới! nó chỉ xóa bản gốc, đã tồn tại!
jasie
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.