Bagaimana cara mendapatkan ID dari baris terakhir yang diperbarui di MySQL?

134

Bagaimana cara mendapatkan ID dari baris terakhir yang diperbarui di MySQL menggunakan PHP?

Avinash
sumber
2
mysqli_insert_id ($ link) akan mengembalikan persis id dari baris terakhir yang diperbarui. Saya menggunakan fungsi ini dalam proyek saya untuk tujuan yang sama. Anda bisa menggunakannya dalam kueri sinkron atau asinkron. Cukup masukkan $ lastupdated_row_id = mysqli_insert_id ($ tautan) ke dalam kode Anda dan itu akan bekerja untuk Anda.
Naeem Ul Wahhab
1
Bukankah Anda sudah tahu ID baris jika Anda memperbarui? Saya kira pasti ada beberapa kasus di mana Anda tidak.
JCharette
1
Anda mungkin menggunakan klausa tempat dalam permintaan pembaruan Anda, mengapa Anda tidak bisa menggunakan klausa tempat yang sama dalam kueri pemilihan? UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1?
Salman A

Jawaban:

236

Saya telah menemukan jawaban untuk masalah ini :)

SET @update_id := 0;
UPDATE some_table SET column_name = 'value', id = (SELECT @update_id := id)
WHERE some_other_column = 'blah' LIMIT 1; 
SELECT @update_id;

EDIT oleh aefxx

Teknik ini dapat dikembangkan lebih lanjut untuk mengambil ID dari setiap baris yang dipengaruhi oleh pernyataan pembaruan:

SET @uids := null;
UPDATE footable
   SET foo = 'bar'
 WHERE fooid > 5
   AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) );
SELECT @uids;

Ini akan mengembalikan string dengan semua ID yang diakhiri dengan koma.

Pomyk
sumber
6
Tidak dapat percaya ini memiliki 0 upvote, dan komentar mysql_insert_id () yang bukan apa yang diminta OP sama sekali memiliki 13. Terima kasih Pomyk, sebuah trik pintar!
Jaka Jančar
1
Karena Anda memiliki WHEREklausa, Anda cukup menggunakan WHEREklausa yang sama dalam permintaan Anda berikutnyaSELECT id FROM footable WHERE fooid > 5
Salman A
4
Mungkin semua orang mengerti ini, tetapi jika Anda menggunakan mysql_query (); Anda harus membaginya menjadi tiga panggilan berbeda, tetapi itu akan berhasil.
rael_kid
8
Bahkan tidak perlu menggunakan variabel. LAST_INSERT_ID()dapat menerima argumen yang akan mengatur nilai yang dikembalikan oleh panggilan berikutnya ke LAST_INSERT_ID(). Sebagai contoh: UPDATE table SET id=LAST_INSERT_ID(id), row='value' WHERE other_row='blah';. Sekarang, SELECT LAST_INSERT_ID();akan mengembalikan id yang diperbarui. Lihat jawaban newtover untuk lebih jelasnya.
Joel
3
@SteveChilds Saya baru saja mengomentari pertanyaan newtover, dan ingin menambahkan solusi ke perangkap yang Anda gambarkan. Set ini LAST_INSERT_ID ke 0 jika tidak ada yang UPDATE: UPDATE lastinsertid_test SET row='value' WHERE row='asd' AND LAST_INSERT_ID(id) OR LAST_INSERT_ID(0);. Namun itu tidak mengambil beberapa id, jadi jawaban ini lebih unggul.
martinczerwi
33

Hm, saya terkejut bahwa di antara jawaban saya tidak melihat solusi termudah.

Misalkan, item_idadalah kolom identitas bilangan bulat dalam itemstabel dan Anda memperbarui baris dengan pernyataan berikut:

UPDATE items
SET qwe = 'qwe'
WHERE asd = 'asd';

Kemudian, untuk mengetahui baris terbaru yang terpengaruh tepat setelah pernyataan, Anda harus sedikit memperbarui pernyataan menjadi yang berikut:

UPDATE items
SET qwe = 'qwe',
    item_id=LAST_INSERT_ID(item_id)
WHERE asd = 'asd';
SELECT LAST_INSERT_ID();

Jika Anda perlu memperbarui hanya baris yang benar-benar berubah, Anda harus menambahkan pembaruan bersyarat dari item_id melalui LAST_INSERT_ID memeriksa apakah data akan berubah di baris.

baru ditemukan
sumber
3
Ini multi-user aman karena banyak klien dapat mengeluarkan pernyataan UPDATE dan mendapatkan nilai urutan mereka sendiri dengan pernyataan SELECT (atau mysql_insert_id ()), tanpa mempengaruhi atau dipengaruhi oleh klien lain yang menghasilkan nilai urutan mereka sendiri. Sesuai dev.mysql.com/doc/refman/5.0/en/…
brutuscat
1
Bukankah ini akan mengatur item_id ke catatan yang dimasukkan terakhir?
arleslie
2
@arleslie, jika Anda mengikuti tautan ke dokumen di komentar brutuscat di atas, Anda akan melihatnya tidak akan. Ini adalah perilaku yang dimaksudkan persis untuk kasus ini.
newtover
1
Ini memang jawaban yang benar. Meskipun kueri tampaknya agak kontra-intuitif, inilah yang persisnya dikatakan oleh Dokumentasi MySQL.
Timothy Zorn
3
Seandainya kueri membingungkan Anda, karena LAST_INSERT_ID (expr) akan mengembalikan nilai expr untuk panggilan UPDATE, Anda juga dapat menggunakannya seperti ini:UPDATE items SET qwe = 'qwe' WHERE asd = 'asd' AND LAST_INSERT_ID(item_id); SELECT LAST_INSERT_ID();
martinczerwi
14

Ini secara resmi sederhana tetapi sangat kontra-intuitif. Jika Anda melakukannya:

update users set status = 'processing' where status = 'pending'
limit 1

Ubah ke ini:

update users set status = 'processing' where status = 'pending'
and last_insert_id(user_id) 
limit 1

Penambahan last_insert_id(user_id)dalam whereklausa memberitahu MySQL untuk mengatur variabel internal ke ID dari baris yang ditemukan. Ketika Anda memberikan nilai last_insert_id(expr)seperti ini, akhirnya mengembalikan nilai itu, yang dalam kasus ID seperti di sini selalu bilangan bulat positif dan karenanya selalu bernilai true, tidak pernah mengganggu klausa di mana. Ini hanya berfungsi jika beberapa baris benar-benar ditemukan, jadi ingatlah untuk memeriksa baris yang terpengaruh. Anda kemudian bisa mendapatkan ID dengan berbagai cara.

MySQL last_insert_id()

Anda dapat membuat urutan tanpa memanggil LAST_INSERT_ID (), tetapi utilitas menggunakan fungsi dengan cara ini adalah bahwa nilai ID dipertahankan di server sebagai nilai yang dihasilkan secara otomatis terakhir. Ini multi-user aman karena banyak klien dapat mengeluarkan pernyataan UPDATE dan mendapatkan nilai urutan mereka sendiri dengan pernyataan SELECT (atau mysql_insert_id ()), tanpa mempengaruhi atau dipengaruhi oleh klien lain yang menghasilkan nilai urutan mereka sendiri.

MySQL mysql_insert_id()

Mengembalikan nilai yang dihasilkan untuk kolom AUTO_INCREMENT oleh pernyataan INSERT atau UPDATE sebelumnya. Gunakan fungsi ini setelah Anda melakukan pernyataan INSERT ke dalam tabel yang berisi bidang AUTO_INCREMENT, atau telah menggunakan INSERT atau UPDATE untuk menetapkan nilai kolom dengan LAST_INSERT_ID (expr).

Alasan perbedaan antara LAST_INSERT_ID () dan mysql_insert_id () adalah bahwa LAST_INSERT_ID () dibuat mudah digunakan dalam skrip sementara mysql_insert_id () mencoba memberikan informasi yang lebih tepat tentang apa yang terjadi pada kolom AUTO_INCREMENT.

PHP mysqli_insert_id()

Melakukan pernyataan INSERT atau UPDATE menggunakan fungsi LAST_INSERT_ID () juga akan mengubah nilai yang dikembalikan oleh fungsi mysqli_insert_id ().

Menyatukan semuanya:

$affected_rows = DB::getAffectedRows("
    update users set status = 'processing' 
    where status = 'pending' and last_insert_id(user_id) 
    limit 1"
);
if ($affected_rows) {
    $user_id = DB::getInsertId();
}

(FYI bahwa kelas DB ada di sini .)

Vladimir Kornea
sumber
Penting untuk dicatat: ini adalah multi-koneksi aman, nilai bertahan untuk last_insert_id atau mysql_insert_id (dan mungkin mysqli_insert_id, saya tidak memeriksa), adalah per-koneksi. Luar biasa!
Ryan S
10

Ini adalah metode yang sama dengan jawaban Salman A, tetapi inilah kode yang harus Anda lakukan.

Pertama, edit tabel Anda sehingga secara otomatis akan melacak setiap kali baris diubah. Hapus baris terakhir jika Anda hanya ingin tahu kapan sebuah baris pertama kali dimasukkan.

ALTER TABLE mytable
ADD lastmodified TIMESTAMP 
    DEFAULT CURRENT_TIMESTAMP 
    ON UPDATE CURRENT_TIMESTAMP;

Kemudian, untuk mengetahui baris terakhir yang diperbarui, Anda dapat menggunakan kode ini.

SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1;

Semua kode ini diangkat dari MySQL vs PostgreSQL: Menambahkan Kolom 'Terakhir Dimodifikasi' ke Tabel dan Manual MySQL: Baris Pengurutan . Saya baru saja mengumpulkannya.

Chad von Nau
sumber
7
Metode ini dapat mengambil id yang salah jika penyisipan kedua dilakukan tepat setelah kueri penyisipan pertama. Namun, jika kita menggunakan 'WHERE' dengan kueri ini yaitu SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1 WHERE (beberapa kondisi yang terkait dengan query insert terakhir), maka itu mungkin mencegah pengambilan id yang salah.
Naeem Ul Wahhab
1
@ TheNoble-Coder Ini benar. Jika Anda ingin agar id baris dipengaruhi permintaan pembaruan tertentu, maka gunakan teknik Pomyk. Teknik ini di sini lebih berguna ketika digunakan secara tidak sinkron, di mana Anda hanya menginginkan pembaruan terakhir absolut.
Chad von Nau
5

Pertanyaan:

$sqlQuery = "UPDATE 
            update_table 
        SET 
            set_name = 'value' 
        WHERE 
            where_name = 'name'
        LIMIT 1;";

Fungsi PHP:

function updateAndGetId($sqlQuery)
{
    mysql_query(str_replace("SET", "SET id = LAST_INSERT_ID(id),", $sqlQuery));
    return mysql_insert_id();
}

Ini bekerja untuk saya;)

GigolNet Guigolachvili
sumber
saya suka sama tapi berlari differntly ref: forums.mysql.com/read.php?52,390616,390619
3

Lebih jauh ke Jawaban Di Atas Diterima
Untuk mereka yang bertanya-tanya tentang :=&=

Perbedaan yang signifikan antara :=dan =, dan itu adalah yang :=berfungsi sebagai operator penugasan variabel di mana saja, sementara =hanya berfungsi seperti itu dalam pernyataan SET, dan merupakan operator perbandingan di mana pun.

Jadi SELECT @var = 1 + 1;akan meninggalkan @vartidak berubah dan mengembalikan boolean (1 atau 0 tergantung pada nilai saat ini dari @var), sementara SELECT @var := 1 + 1;akan berubah @varmenjadi 2 , dan mengembalikan 2 . [Sumber]

An3030
sumber
Hei, terima kasih. Apa yang mereka maksud sebenarnya lebih menarik daripada jawaban yang diterima di atas.
Hijau
2

Hei, aku hanya butuh trik seperti itu - aku menyelesaikannya dengan cara yang berbeda, mungkin itu akan berhasil untukmu. Perhatikan ini bukan solusi yang dapat diskalakan dan akan sangat buruk untuk set data besar.

Pisahkan permintaan Anda menjadi dua bagian -

pertama, pilih id dari baris yang ingin Anda perbarui dan simpan di tabel sementara.

kedua, lakukan pembaruan asli dengan kondisi dalam pernyataan pembaruan diubah menjadi where id in temp_table.

Dan untuk memastikan konkurensi, Anda perlu mengunci tabel sebelum dua langkah ini dan kemudian lepaskan kunci di akhir.

Sekali lagi, ini bekerja untuk saya, untuk kueri yang berakhir dengan limit 1, jadi saya bahkan tidak menggunakan tabel temp, tetapi hanya sebuah variabel untuk menyimpan hasil yang pertama select.

Saya lebih suka metode ini karena saya tahu saya akan selalu memperbarui hanya satu baris, dan kodenya mudah.

olamundo
sumber
2
SET @uids := "";
UPDATE myf___ingtable
   SET id = id
   WHERE id < 5
  AND ( SELECT @uids := CONCAT_WS(',', CAST(id AS CHAR CHARACTER SET utf8), @uids) );
SELECT @uids;

Saya harus CAST id (tidak tahu kenapa) ... atau saya tidak bisa mendapatkan konten @ids (itu adalah gumpalan) Btw banyak terima kasih atas jawaban Pomyk!

Gromish
sumber
2

ID dari baris yang terakhir diperbarui adalah ID yang sama yang Anda gunakan di 'updateQuery' untuk menemukan & memperbarui baris itu. Jadi, simpan saja (panggil) ID itu di yang Anda inginkan.

last_insert_id()tergantung pada AUTO_INCREMENT, tetapi ID yang terakhir diperbarui tidak.

Driada
sumber
3
Bagaimana jika pembaruan tidak dilakukan dari id, melainkan set atribut yang lain?
Sebas
2

Solusi saya adalah, pertama-tama tentukan "id" (@uids) dengan perintah pilih dan setelah perbarui id ini dengan @uids.

SET @uids := (SELECT id FROM table WHERE some = 0 LIMIT 1);
UPDATE table SET col = 1 WHERE id = @uids;SELECT @uids;

itu berhasil pada proyek saya.

Ahmet Uğur
sumber
1

Jika Anda hanya melakukan penyisipan, dan ingin satu dari sesi yang sama, lakukan sesuai jawaban peirix. Jika Anda melakukan modifikasi, Anda perlu memodifikasi skema basis data Anda untuk menyimpan entri mana yang terakhir diperbarui.

Jika Anda ingin id dari modifikasi terakhir, yang mungkin berasal dari sesi yang berbeda (yaitu bukan yang baru saja dilakukan oleh kode PHP yang berjalan saat ini, tetapi yang dilakukan sebagai tanggapan atas permintaan yang berbeda), Anda dapat menambahkan Kolom TIMESTAMP ke tabel Anda disebut last_modified (lihat http://dev.mysql.com/doc/refman/5.1/en/datetime.html untuk informasi), dan kemudian ketika Anda memperbarui, atur last_modified = CURRENT_TIME.

Setelah menetapkan ini, Anda dapat menggunakan kueri seperti: SELECT id FROM table ORDER BY last_modified DESC LIMIT 1; untuk mendapatkan baris yang paling baru dimodifikasi.

a1kmm
sumber
-9

Tidak perlu kode Mysql begitu lama. Di PHP, kueri akan terlihat seperti ini:

$updateQuery = mysql_query("UPDATE table_name SET row='value' WHERE id='$id'") or die ('Error');
$lastUpdatedId = mysql_insert_id();
Driada
sumber