Uzyskać nowy rekord klucza podstawowego ID z zapytania wstawiania mysql?

249

Ok, powiedzmy, że robię mysql INSERTw jednej z moich tabel, a tabela ma kolumnę item_idustawioną na autoincrementi primary key.

Jak uzyskać zapytanie, aby wyświetlało wartość nowo wygenerowanego klucza podstawowego item_idw tym samym zapytaniu?

Obecnie uruchamiam drugie zapytanie w celu odzyskania identyfikatora, ale nie wydaje się to dobrą praktyką, ponieważ może to spowodować niewłaściwy wynik ...

Jeśli nie jest to możliwe, jaka jest najlepsza praktyka, aby upewnić się, że odzyskam prawidłowy identyfikator?

Amy Neville
źródło
1
Nie ma sposobu na zwrócenie czegokolwiek z takiego INSERTzapytania; jak myślisz, dlaczego może to dać zły wynik?
Explosion Pills
4
Cóż, jeśli proces jest wykonywany przez 2 osoby osobno, możesz uzyskać nakładającą się listę procesów, myślę - skoro musisz wykonać 2 oddzielne zapytania?
Amy Neville,
@JimFell tak, to w zasadzie to samo pytanie, ale na to pytanie ma ogólnie lepsze odpowiedzi
RozzA
1
Użyj postgresql, a następnie zrób to tak: INSERT INTO table (col1, col2) VALUES (val1, val2) ID POWRÓT lub INSERT INTO table (col1, col2) VALUES (val1, val2) RETURNING * lub UPDATE table SET col1 = val1, col2 = val2 WHERE instrukcja RETURNING id lub UPDATE tabela SET (col1, col2) = (val1, val2) WHERE instrukcja RETURNING id lub UPDATE tabela SET (col1, col2) = (val1, val2) WHERE instrukcja RETURNING *
gdarcan

Odpowiedzi:

327

Musisz użyć LAST_INSERT_ID()funkcji: http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

Na przykład:

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

To cię z powrotem na PRIMARY KEYwartość ostatniego wiersza, który jesteś w brzmieniu:

Wygenerowany identyfikator jest przechowywany na serwerze na podstawie połączenia . Oznacza to, że wartość zwrócona przez funkcję do danego klienta jest pierwszą wartością AUTO_INCREMENT wygenerowaną dla najnowszej instrukcji wpływającej na kolumnę AUTO_INCREMENT przez tego klienta .

Tak więc wartość zwracana przez LAST_INSERT_ID()jest na użytkownika i nie ma na nią wpływu inne zapytania, które mogą być uruchomione na serwerze od innych użytkowników .

Zamek Duncana
źródło
8
tak, ale co jeśli w międzyczasie (między zapytaniami na liście procesów) wstawiono jakiś inny wiersz? Czy jest jakiś sposób, aby napisać zapytanie wstawiania, aby wyprowadzało to?
Amy Neville,
Ok, rozumiem ... ostatni identyfikator wstawiania zapytania jest zapisywany, nawet jeśli nie jest zalogowany w wyniku ... $ mysqli-> insert_id
Amy Neville
27
To cię z powrotem na PRIMARY KEYwartość ostatniego wiersza, który jesteś wstawiony, bo to na połączenie - każde połączenie z serwerem będzie utrzymywać swój własny stosunek do tego. Zaktualizowałem odpowiedź, aby to wyjaśnić.
Duncan Lock
Załóżmy więc, że 3 użytkowników jednocześnie opublikowało swoje formularze, a moja baza danych musi je wprowadzić. Chcę dodać wiersz odpowiadający każdemu nowo utworzonemu identyfikatorowi table1 w table2. Czy współbieżność jest obsługiwana, czy będę musiał to zrobić ręcznie w PHP dla przychodzących żądań zapisu do bazy danych?
bad_keypoints
Jeśli w punkcie, w którym wykonujesz wstawianie tabeli 1, baza danych zna wszystkie informacje, które chcesz wstawić do tabeli 2, możesz użyć wyzwalacza, aby to zrobić, lub połączyć to w zapytanie. Jeśli nie, musisz użyć wielu zapytań - tzn. Zrób to w PHP. To zależy od tego, jakie są dane i skąd pochodzą dla drugiej wkładki.
Duncan Lock
21

UWAGA! z „LAST_INSERT_ID ()”, jeśli próbujesz zwrócić tę wartość klucza podstawowego w PHP.

Wiem, że ten wątek nie jest oznaczony jako php, ale dla każdego, kto natknął się na tę odpowiedź, chcąc zwrócić identyfikator wstawki MySQL ze wstawki skryptowej PHP przy użyciu standardowych wywołań mysql_query - nie zadziała i nie będzie oczywisty bez przechwytywania błędów SQL.

Nowsze mysqli obsługuje wiele zapytań - które LAST_INSERT_ID () faktycznie jest drugim zapytaniem z oryginału.

IMO osobny WYBÓR, aby zidentyfikować ostatni klucz podstawowy, jest bezpieczniejszy niż opcjonalna funkcja mysql_insert_id () zwracająca identyfikator AUTO_INCREMENT wygenerowany z poprzedniej operacji WSTAWIANIA.

Martin Sansone - MiOEE
źródło
7
LAST_INSERT_IDjest funkcją MySQL dla każdego połączenia. Jeśli zapytasz o ostatni identyfikator wstawiania, możliwe jest, że oddzielne połączenie wykona zapis i będziesz mieć zły identyfikator.
Pigułki przeciwwybuchowe
@ExplosionPills mysql_insert_id()działa również dla poszczególnych połączeń, ale ma również dziwne zachowanie, jak widać tutaj stackoverflow.com/a/897374/1305910 w komentarzu Cliffordlife - nieważne, że wszyscy powinniśmy używaćmysqli
RozzA
czy możesz wyjaśnić, co masz na myśli mówiąc, że „to nie zadziała”?
john ktejik
18

Z LAST_INSERT_ID()dokumentacji:

Wygenerowany identyfikator jest przechowywany na serwerze na podstawie połączenia

To znaczy, jeśli masz dwa oddzielne żądania do skryptu jednocześnie, nie będą one wpływać na siebie nawzajem LAST_INSERT_ID()(chyba że używasz trwałego połączenia).

Pigułki przeciwwybuchowe
źródło
2
Myślę, że wątpliwe jest, jeśli twoja tabela ma wyzwalacz, który wstawia do innej tabeli .... LAST_INSERT_ID () zwróci wartość identyfikatora drugiej tabeli ..
bgies
15

Oto czego szukasz !!!

select LAST_INSERT_ID()

Jest to najlepsza alternatywa SCOPE_IDENTITY()funkcji używanej w SQL Server.

Musisz również pamiętać, że zadziała to tylko wtedy, gdy Last_INSERT_ID()zostaniesz zwolniony po Insertzapytaniu. Oznacza to, że zapytanie zwraca identyfikator wstawiony do schematu. Nie można uzyskać ostatniego wstawionego identyfikatora konkretnej tabeli.

Aby uzyskać więcej informacji, proszę przejść przez link Odpowiednik funkcji SQLServer SCOPE_IDENTITY () w mySQL?

PVR
źródło
6

Jeśli potrzebujesz wartości przed wstawieniem wiersza:

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

Możesz użyć tego we wstawce:

INSERT INTO
    document (Code, Title, Body)
VALUES (                
    sha1( concat (convert ( now() , char), ' ',   getAutoincrementalNextval ('document') ) ),
    'Title',
    'Body'
);
Paulo A. Costa
źródło
1
Ten nie wydaje się dobrym pomysłem? Jeśli 2 klientów wywołuje tę funkcję w tym samym czasie, będą myśleć, że wstawiają ten sam identyfikator, podczas gdy w rzeczywistości tak nie jest ... jeden będzie nieco wolniejszy na wstawce i otrzyma kolejny identyfikator bez wiedzy.
CarCar
5

Otrzymasz następujące parametry w wyniku zapytania:

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

insertIdJest dokładnie to, czego potrzebujesz.

(NodeJS-mySql)

MESepehr
źródło
4

Jeśli w Pythonie używasz pymysql, z kursora możesz użyć kursor.strowid

mojoken
źródło
2

wystarczy użyć „$ last_id = mysqli_insert_id ($ conn);”

Arnav Singh
źródło
2
Natknąłem się tutaj, szukając wersji php tej odpowiedzi dzięki Google, więc zagłosowałem za odpowiedzią. Choć technicznie rzecz biorąc, OP nie poprosił o php, może to być pomocne dla wielu osób, które również się tutaj potykają.
Fotograf Britt
Dziękuję bardzo Arnav! I
JuanSedano
1

Jeśli używasz PHP: Na obiekcie PDO możesz po prostu wstawić metodę lastInsertId po wstawieniu.

W przeciwnym razie za pomocą LAST_INSERT_ID możesz uzyskać następującą wartość:SELECT LAST_INSERT_ID();

Olafnyr
źródło
0

użyłem return $this->db->insert_id();Codeigniter

Hamza Saeed
źródło
0

Chcę tylko podzielić się moim podejściem do tego w PHP, niektórzy z was mogą uznać, że nie jest to skuteczny sposób, ale jest to 100 lepiej niż inne dostępne opcje.

wygeneruj losowy klucz i wstaw go do tabeli, tworząc nowy wiersz. następnie możesz użyć tego klucza, aby pobrać klucz podstawowy. użyj aktualizacji, aby dodać dane i robić inne rzeczy.

w ten sposób pomaga zabezpieczyć wiersz i mieć prawidłowy klucz podstawowy.

Naprawdę nie polecam tego, chyba że nie masz innych opcji.

Singh G.
źródło