Tabel MySql Sisipkan jika tidak ada jika tidak update

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

Ini berfungsi jika datenumada, tetapi saya ingin memasukkan data ini sebagai baris baru jika datenumtidak ada.

MEMPERBARUI

datenum itu unik tapi itu bukan kunci utama

OHLÁLÁ
sumber
2
Apakah "datenum" unik? Anda dapat menggunakan INSERT ... ON DUPLICATE KEY UPDATE jika ya.
Yakub

Jawaban:

143

Jai benar yang harus Anda gunakan INSERT ... ON DUPLICATE KEY UPDATE.

Perhatikan bahwa Anda tidak perlu menyertakan datenum dalam klausa pembaruan karena ini adalah kunci unik, jadi tidak boleh berubah. Anda perlu memasukkan semua kolom lain dari tabel Anda. Anda dapat menggunakan VALUES()fungsi ini untuk memastikan nilai yang tepat digunakan saat memperbarui kolom lain.

Ini pembaruan Anda yang ditulis ulang menggunakan INSERT ... ON DUPLICATE KEY UPDATEsintaks yang tepat untuk MySQL:

INSERT INTO AggregatedData (datenum,Timestamp)
VALUES ("734152.979166667","2010-01-14 23:30:00.000")
ON DUPLICATE KEY UPDATE 
  Timestamp=VALUES(Timestamp)
Ike Walker
sumber
18
Hati-hati saat menggunakan INSERT ... ON DUPLICATE KEY UPDATE pada tabel dengan tabel yang memiliki lebih dari satu kunci unik atau primer. Diambil dari dokumentasi MySQL : Selain itu, dimulai dengan MySQL 5.5.24, pernyataan INSERT ... ON DUPLICATE KEY UPDATE terhadap tabel yang memiliki lebih dari satu kunci unik atau primer juga ditandai sebagai tidak aman. (Bug # 11765650, Bug # 58637) Bug 58637 deskripsi bugs.mysql.com/bug.php?id=58637
broadband
1
Mungkin diperlukan untuk membuat UNIQUEbatasan Timestampdengan menggunakanALTER TABLE AggregatedData ADD UNIQUE (Timestamp)
Avyakt
@broadband Anda dapat menggunakan kunci komposit untuk menghindari bug ini
Kareem
16

Coba gunakan ini :

Jika Anda menentukan ON DUPLICATE KEY UPDATE, dan sebuah baris disisipkan yang akan menyebabkan nilai duplikat dalam UNIQUE index orPRIMARY KEY , MySQL performs an [UPDATE`] ( http://dev.mysql.com/doc/refman/5.7/en/update.html ) dari baris lama. ..

The ON DUPLICATE KEY UPDATEklausul dapat berisi beberapa tugas kolom, dipisahkan dengan koma.

Dengan ON DUPLICATE KEY UPDATE, nilai baris yang terpengaruh per baris adalah 1 jika baris disisipkan sebagai baris baru, 2 jika baris yang ada diperbarui, dan 0 jika baris yang sudah ada disetel ke nilai saat ini. Jika Anda menentukan CLIENT_FOUND_ROWSbendera untuk mysql_real_connect()saat menyambung ke mysqld , nilai baris yang terpengaruh adalah 1 (bukan 0) jika baris yang ada disetel ke nilai saat ini ...

Jai
sumber
Tapi datenum saya bukan primary key.
OHLÁLÁ
Jadi dalam kasus saya apa solusinya, saya mencoba yang ini, tanpa solusi apa pun: INSERT INTO forwind.aggregateddata (datenum, Timestamp, Min_F1_baro_20_) NILAI ('1', '2', '3') ON DUPLICATE KEY UPDATE datenum = datenum;
OHLÁLÁ
1
apakah datenum seharusnya unik? jika ya, daripada menambahkan indeks unik ke dalamnya (jika belum ditambahkan) Maka itu akan berhasil. Lihat dev.mysql.com/doc/refman/5.1/en/alter-table.html untuk cara memasang indeks UNIK
Jai
sekarang saya mendefinisikan datenum sebagai unik, dan berfungsi dengan baik, terima kasih
OHLÁLÁ
1
Hanya link, mungkin memberikan jawaban.
Andrew
0

Saya mengalami situasi di mana saya perlu memperbarui atau menyisipkan pada tabel sesuai dengan dua bidang (keduanya kunci asing) di mana saya tidak dapat mengatur batasan UNIK (jadi INSERT ... ON DUPLICATE KEY UPDATE tidak akan berfungsi). Inilah yang akhirnya saya gunakan:

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;

Contoh ini diambil dari salah satu database saya, dengan parameter input (dua nama dan angka) diganti dengan [hasher_name], [hash_name], dan [new_value]. SELECT ... LIMIT 1 yang bersarang menarik yang pertama dari record yang ada atau record baru (last_recogs.id adalah kunci primer autoincrement) dan menggunakannya sebagai masukan nilai ke REPLACE INTO.

salfter
sumber
REPLACE selalu menyisipkan baris baru! itu hanya menghapus yang asli, yang sudah ada!
jasie