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?


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 .


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.


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).


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?


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'
);

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)


4

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


2

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


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



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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.