Dapatkan ID kunci primer rekaman baru dari permintaan sisipan mysql?

249

Ok, jadi katakanlah saya sedang melakukan mysql INSERTke salah satu tabel saya dan tabel tersebut memiliki kolom item_idyang diatur ke autoincrementdan primary key.

Bagaimana cara mendapatkan kueri untuk menampilkan nilai kunci primer yang baru dibuat item_iddalam kueri yang sama?

Saat ini saya menjalankan kueri kedua untuk mengambil id tetapi ini sepertinya bukan praktik yang baik mengingat ini mungkin menghasilkan hasil yang salah ...

Jika ini tidak memungkinkan, apa praktik terbaik untuk memastikan saya mendapatkan id yang benar?

Amy Neville
sumber
1
Tidak ada cara untuk mengembalikan apa pun dari INSERTpermintaan seperti itu; mengapa Anda berpikir itu mungkin menghasilkan hasil yang salah?
Pil Explosion
4
Nah, jika proses dijalankan oleh 2 orang secara terpisah maka Anda bisa mendapatkan daftar proses yang tumpang tindih saya pikir - karena Anda harus menjalankan 2 pertanyaan terpisah?
Amy Neville
Kemungkinan duplikat baris sisipan PHP / MySQL lalu dapatkan 'id'
Jim Fell
@ JimFell ya itu pada dasarnya pertanyaan yang sama, tetapi yang ini memiliki jawaban yang jauh lebih baik secara umum
RozzA
1
Gunakan postgresql kemudian lakukan seperti ini INSERT INTO table (col1, col2) VALUES (val1, val2) KEMBALI id atau INSERT INTO table (col1, col2) VALUES (val1, val2) RETURNING * atau UPDATE table SET col1 = val1, col2 = val2 WHERE statement RETURNING id atau SET tabel UPDATE (col1, col2) = (val1, val2) WHERE statement RETURNING id atau SET tabel pemutakhiran (col1, col2) = (val1, val2) WHERE statement
RETURNING

Jawaban:

326

Anda harus menggunakan LAST_INSERT_ID()fungsi: http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

Misalnya:

INSERT INTO table_name (col1, col2,...) VALUES ('val1', 'val2'...);
SELECT LAST_INSERT_ID();

Ini akan mengembalikan PRIMARY KEYnilai baris terakhir yang Anda masukkan:

ID yang dihasilkan dipertahankan di server berdasarkan per koneksi . Ini berarti bahwa nilai yang dikembalikan oleh fungsi ke klien yang diberikan adalah nilai AUTO_INCREMENT pertama yang dihasilkan untuk pernyataan terbaru yang memengaruhi kolom AUTO_INCREMENT oleh klien itu .

Jadi nilai yang dikembalikan oleh LAST_INSERT_ID()adalah per pengguna dan tidak terpengaruh oleh kueri lain yang mungkin berjalan di server dari pengguna lain .

Duncan Lock
sumber
8
ya tetapi bagaimana jika dalam sementara (antara permintaan dalam daftar proses) beberapa baris lain telah dimasukkan? Apakah ada cara untuk menulis kueri sisipan sehingga menghasilkan ini?
Amy Neville
Oke, saya mengerti ... id insert terakhir dari query dicatat walaupun itu tidak masuk dalam hasil ... $ mysqli-> insert_id
Amy Neville
27
Ini akan mengembalikan PRIMARY KEYnilai baris terakhir yang Anda masukkan, karena per koneksi - setiap koneksi ke server akan mempertahankan nilainya sendiri untuk ini. Saya telah memperbarui jawaban untuk memperjelas ini.
Duncan Lock
Jadi misalkan 3 pengguna secara bersamaan memposting formulir mereka dan database saya harus memasukkannya. Saya ingin menambahkan baris yang sesuai dengan setiap ID table1 yang baru dibuat di table2. Apakah konkurensi ditangani atau haruskah saya melakukannya dalam PHP secara manual, untuk permintaan penulisan basis data yang masuk?
bad_keypoints
Jika, pada saat Anda melakukan insert table1, database tahu semua informasi yang ingin Anda masukkan ke table2, maka Anda bisa menggunakan pemicu untuk melakukan ini, atau menggabungkan ini ke dalam kueri. Jika tidak, maka Anda harus menggunakan beberapa kueri - yaitu melakukannya dalam PHP. Itu tergantung pada apa data itu dan dari mana datangnya untuk memasukkan kedua.
Duncan Lock
21

WASPADALAH !! dari "LAST_INSERT_ID ()" jika mencoba mengembalikan nilai kunci utama ini dalam PHP.

Saya tahu utas ini bukan tag php, tetapi bagi siapa pun yang menemukan jawaban ini ingin mengembalikan id penyisipan MySQL dari sisipan skrip PHP menggunakan panggilan mysql_query standar - tidak akan berfungsi dan tidak jelas tanpa menangkap kesalahan SQL.

Mysqli yang lebih baru mendukung banyak kueri - yang LAST_INSERT_ID () sebenarnya adalah kueri kedua dari yang asli.

IMO SELECT terpisah untuk mengidentifikasi kunci primer terakhir lebih aman daripada fungsi mysql_insert_id () opsional yang mengembalikan ID AUTO_INCREMENT yang dihasilkan dari operasi INSERT sebelumnya.

Martin Sansone - MiOEE
sumber
7
LAST_INSERT_IDadalah fungsi MySQL per-koneksi. Jika Anda meminta ID sisipan terakhir, ada kemungkinan koneksi yang terpisah akan melakukan penulisan dan Anda akan memiliki ID yang salah.
Pil Ledakan
@ExplosionPills mysql_insert_id()juga berfungsi atas dasar per koneksi, tetapi juga menderita perilaku aneh seperti yang terlihat di sini stackoverflow.com/a/897374/1305910 dalam komentar oleh Cliffordlife - tidak pernah kita semua seharusnya menggunakanmysqli
RozzA
dapatkah Anda mengklarifikasi apa yang Anda maksud ketika Anda tetap 'tidak akan bekerja'?
john ktejik
18

Dari LAST_INSERT_ID()dokumentasi:

ID yang dihasilkan dipertahankan di server berdasarkan per koneksi

Itu adalah jika Anda memiliki dua permintaan terpisah untuk skrip secara bersamaan, mereka tidak akan memengaruhi satu sama lain LAST_INSERT_ID()(kecuali jika Anda menggunakan koneksi persisten mungkin).

Pil Ledakan
sumber
2
Saya pikir ini meragukan jika meja Anda memiliki pemicu di atasnya yang melakukan penyisipan ke tabel lain .... LAST_INSERT_ID () akan mengembalikan nilai id dari tabel lain ..
bgies
15

Di sini apa yang Anda cari !!!

select LAST_INSERT_ID()

Ini adalah alternatif SCOPE_IDENTITY()fungsi terbaik yang digunakan di SQL Server.

Anda juga harus ingat bahwa ini hanya akan berfungsi jika Last_INSERT_ID()dipecat mengikuti Insertpermintaan Anda . Itu adalah permintaan mengembalikan id yang dimasukkan dalam skema. Anda tidak bisa mendapatkan id yang dimasukkan terakhir pada tabel tertentu.

Untuk perincian lebih lanjut, silakan buka tautan Setara dengan fungsi SQLServer SCOPE_IDENTITY () di mySQL?

PVR
sumber
6

Jika Anda membutuhkan nilai sebelum menyisipkan baris:

CREATE FUNCTION `getAutoincrementalNextVal`(`TableName` VARCHAR(50))
    RETURNS BIGINT
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN

    DECLARE Value BIGINT;

    SELECT
        AUTO_INCREMENT INTO Value
    FROM
        information_schema.tables
    WHERE
        table_name = TableName AND
        table_schema = DATABASE();

    RETURN Value;

END

Anda dapat menggunakan ini di sisipan:

INSERT INTO
    document (Code, Title, Body)
VALUES (                
    sha1( concat (convert ( now() , char), ' ',   getAutoincrementalNextval ('document') ) ),
    'Title',
    'Body'
);
Paulo A. Costa
sumber
1
Yang ini sepertinya bukan ide yang bagus? Jika 2 klien memanggil fungsi itu pada saat yang sama, mereka akan berpikir mereka memasukkan id yang sama padahal kenyataannya tidak .... satu akan sedikit lebih lambat pada sisipan dan mendapatkan ID berikutnya tanpa mengetahuinya.
CarCar
5

Anda akan menerima parameter ini pada hasil permintaan Anda:

    "fieldCount": 0,
    "affectedRows": 1,
    "insertId": 66,
    "serverStatus": 2,
    "warningCount": 1,
    "message": "",
    "protocol41": true,
    "changedRows": 0

The insertIdadalah apa yang Anda butuhkan.

(NodeJS-mySql)

MESepehr
sumber
4

Jika dalam python menggunakan pymysql, dari kursor Anda dapat menggunakan cursor.lastrowid

mojoken
sumber
2

cukup gunakan "$ last_id = mysqli_insert_id ($ conn);"

Arnav Singh
sumber
2
Saya sebenarnya tersandung di sini mencari versi php dari jawaban ini terima kasih kepada google, jadi saya memilih jawaban ini. Meskipun secara teknis OP tidak meminta php, ini bisa membantu banyak orang yang tersandung di sini juga.
Fotografer Britt
Arnav terima kasih banyak! I
JuanSedano
1

Jika Anda menggunakan PHP: Pada objek PDO Anda dapat dengan mudah memanggil metode lastInsertId setelah Anda memasukkan.

Kalau tidak, dengan LAST_INSERT_ID Anda bisa mendapatkan nilai seperti ini:SELECT LAST_INSERT_ID();

Olafnyr
sumber
0

saya digunakan return $this->db->insert_id();untuk Codeigniter

Hamza Saeed
sumber
0

Saya hanya ingin berbagi pendekatan saya dalam hal ini di PHP, beberapa dari Anda mungkin menemukan itu bukan cara yang efisien tetapi ini adalah 100 lebih baik daripada opsi lain yang tersedia.

buat kunci acak dan masukkan ke dalam tabel yang membuat baris baru. maka Anda dapat menggunakan kunci itu untuk mengambil kunci utama. gunakan pembaruan untuk menambahkan data dan melakukan hal-hal lain.

melakukan cara ini membantu mengamankan satu baris dan memiliki kunci primer yang benar.

Saya benar-benar tidak merekomendasikan ini kecuali Anda tidak memiliki opsi lain.

Singh G
sumber