Holen Sie sich die neue Datensatz-Primärschlüssel-ID von der MySQL-Einfügeabfrage?


249

Ok, nehmen wir an, ich mache ein MySQL INSERTin einer meiner Tabellen und die Tabelle hat die Spalte, item_iddie auf autoincrementund gesetzt ist primary key.

Wie kann ich die Abfrage veranlassen, den Wert des neu generierten Primärschlüssels item_idin derselben Abfrage auszugeben ?

Derzeit führe ich eine zweite Abfrage aus, um die ID abzurufen, aber dies scheint kaum eine gute Vorgehensweise zu sein, da dies möglicherweise zu einem falschen Ergebnis führt ...

Wenn dies nicht möglich ist, wie kann ich dann sicherstellen, dass ich die richtige ID abrufe?


1
Es gibt keine Möglichkeit, eine INSERTsolche Abfrage zurückzugeben. Warum könnte es Ihrer Meinung nach zu einem falschen Ergebnis führen?
Explosion Pills

4
Nun, wenn der Prozess von 2 Personen separat ausgeführt wird, könnten Sie eine überlappende Prozessliste erhalten, denke ich - da Sie 2 separate Abfragen ausführen müssen?
Amy Neville


@ JimFell ja, es ist im Grunde die gleiche Frage, aber diese hat viel bessere Antworten im Allgemeinen
RozzA

1
Verwenden Sie postgresql und machen Sie dann diese INSERT INTO-Tabelle (col1, col2) VALUES (val1, val2) RETURNING id oder INSERT INTO-Tabelle (col1, col2) VALUES (val1, val2) RETURNING * oder UPDATE-Tabelle SET col1 = val1, col2 = val2 WHERE-Anweisung RETURNING id oder UPDATE-Tabelle SET (col1, col2) = (val1, val2) WHERE-Anweisung RETURNING id oder UPDATE-Tabelle SET (col1, col2) = (val1, val2) WHERE-Anweisung RETURNING *
gdarcan

Antworten:


326

Sie müssen die LAST_INSERT_ID()Funktion verwenden: http://dev.mysql.com/doc/refman/5.0/de/information-functions.html#function_last-insert-id

Z.B:

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

Dies wird Ihnen den Rücken PRIMARY KEYWert der letzten Zeile , die Sie eingefügt:

Die generierte ID wird pro Verbindung auf dem Server verwaltet . Dies bedeutet, dass der von der Funktion an einen bestimmten Client zurückgegebene Wert der erste AUTO_INCREMENT-Wert ist, der für die letzte Anweisung generiert wurde, die eine AUTO_INCREMENT-Spalte von diesem Client betrifft .

So kehrte der Wert von LAST_INSERT_ID()ist pro Benutzer und ist unbeeinflusst von anderen Abfragen , die auf dem Server ausgeführt werden können von anderen Benutzern .


8
Ja, aber was ist, wenn in der Zwischenzeit (zwischen Abfragen in der Prozessliste) eine andere Zeile eingefügt wurde? Gibt es eine Möglichkeit, die Einfügeabfrage so zu schreiben, dass sie diese ausgibt?
Amy Neville

Ok, ich verstehe ... die letzte Einfügungs-ID der Abfrage wird aufgezeichnet, auch wenn sie nicht im Ergebnis protokolliert ist ... $ mysqli-> insert_id
Amy Neville

27
Dadurch erhalten Sie den PRIMARY KEYWert der letzten Zeile zurück, die Sie erstellt haben eingefügt, da es pro Verbindung ist - jede Verbindung zum Server wird beibehalten ein eigener Wert für diese ist. Ich habe die Antwort aktualisiert, um dies zu verdeutlichen.
Duncan Lock

Angenommen, 3 Benutzer haben gleichzeitig ihre Formulare gepostet und meine Datenbank muss sie eingeben. Ich möchte eine Zeile hinzufügen, die jeder neu erstellten ID von Tabelle1 in Tabelle2 entspricht. Wird für die Parallelität gesorgt oder muss ich dies in PHP manuell für eingehende Datenbankschreibanforderungen tun?
bad_keypoints

Wenn die Datenbank zu dem Zeitpunkt, an dem Sie die Tabelle1 einfügen, alle Informationen kennt, die Sie in Tabelle2 einfügen möchten, können Sie dazu einen Trigger verwenden oder diese zu einer Abfrage kombinieren. Wenn nicht, müssten Sie mehrere Abfragen verwenden - dh in PHP. Dies hängt davon ab, was die Daten sind und woher sie für die zweite Einfügung stammen.
Duncan Lock

21

IN ACHT NEHMEN !! von "LAST_INSERT_ID ()", wenn versucht wird, diesen Primärschlüsselwert in PHP zurückzugeben.

Ich weiß, dass dieser Thread nicht mit PHP gekennzeichnet ist, aber für alle, die auf diese Antwort gestoßen sind und eine MySQL-Einfügungs-ID von einer PHP-Skript-Einfügung mit Standardaufrufen von mysql_query zurückgeben möchten - dies funktioniert nicht und ist ohne Erfassung von SQL-Fehlern nicht offensichtlich.

Das neuere mysqli unterstützt mehrere Abfragen - wobei LAST_INSERT_ID () tatsächlich eine zweite Abfrage aus dem Original ist.

IMO ist ein separates SELECT zur Identifizierung des letzten Primärschlüssels sicherer als die optionale Funktion mysql_insert_id (), die die aus der vorherigen INSERT-Operation generierte AUTO_INCREMENT-ID zurückgibt.


7
LAST_INSERT_IDist eine MySQL-Funktion pro Verbindung. Wenn Sie nach der letzten Einfügungs-ID fragen, hat möglicherweise eine separate Verbindung einen Schreibvorgang ausgeführt und Sie haben die falsche ID.
Explosion Pills

@ExplosionPills mysql_insert_id()funktioniert auch auf einer Basis pro Verbindung, aber es leidet auch seltsame Verhalten wie hier zu sehen stackoverflow.com/a/897374/1305910 im Kommentar von Cliffordlife - macht nichts , wir sollten alle verwendet habenmysqli
Rozza

Kannst du klarstellen, was du meinst, wenn du bleibst? Es wird nicht funktionieren.
John Ktejik

18

Von dem LAST_INSERT_ID() Dokumentation:

Die generierte ID wird pro Verbindung auf dem Server verwaltet

Wenn Sie zwei separate Anforderungen gleichzeitig an das Skript haben, wirken sich diese nicht gegenseitig aus LAST_INSERT_ID()(es sei denn, Sie verwenden möglicherweise eine dauerhafte Verbindung).


2
Ich denke, es ist zweifelhaft, ob Ihre Tabelle einen Auslöser hat, der eine Einfügung in eine andere Tabelle vornimmt .... LAST_INSERT_ID () gibt den ID-Wert der anderen Tabelle zurück.
bgies

15

Hier was Sie suchen !!!

select LAST_INSERT_ID()

Dies ist die beste Alternative von SCOPE_IDENTITY() Funktion, in der verwendet wird SQL Server.

Sie müssen auch bedenken, dass dies nur funktioniert, wenn Last_INSERT_ID()es von Ihnen ausgelöst wirdInsert Abfrage . Das heißt, die Abfrage gibt die in das Schema eingefügte ID zurück. Sie können die zuletzt eingefügte ID einer bestimmten Tabelle nicht abrufen.

Weitere Informationen finden Sie unter dem Link Das Äquivalent der SQLServer-Funktion SCOPE_IDENTITY () in mySQL?


6

Wenn Sie den Wert benötigen, bevor Sie eine Zeile einfügen:

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

Sie können dies in einer Beilage verwenden:

INSERT INTO
    document (Code, Title, Body)
VALUES (                
    sha1( concat (convert ( now() , char), ' ',   getAutoincrementalNextval ('document') ) ),
    'Title',
    'Body'
);

1
Dieser scheint keine gute Idee zu sein? Wenn 2 Clients diese Funktion gleichzeitig aufrufen, denken sie, dass sie dieselbe ID einfügen, obwohl dies in Wirklichkeit nicht der Fall ist. Einer wird beim Einfügen etwas langsamer sein und die nächste ID erhalten, ohne dass dies bekannt ist.
CarCar

5

Sie erhalten diese Parameter in Ihrem Abfrageergebnis:

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

Das insertIdist genau das, was Sie brauchen.

(NodeJS-mySql)


4

Wenn Sie in Python pymysql verwenden, können Sie vom Cursor aus cursor.lastrowid verwenden


2

benutze einfach "$ last_id = mysqli_insert_id ($ conn);"


2
Ich bin hier tatsächlich gestolpert und habe dank Google nach der PHP-Version dieser Antwort gesucht, also habe ich diese Antwort abgestimmt. Technisch gesehen hat das OP nicht nach PHP gefragt, aber dies könnte für viele Leute hilfreich sein, die auch hier stolpern.
Fotograf Britt

Vielen Dank Arnav! I
JuanSedano

1

Wenn Sie PHP verwenden: Auf einem PDO- Objekt können Sie nach dem Einfügen einfach die lastInsertId- Methode aufrufen .

Andernfalls können Sie mit einer LAST_INSERT_ID den folgenden Wert erhalten:SELECT LAST_INSERT_ID();



0

Ich möchte nur meinen Ansatz dazu in PHP teilen. Einige von Ihnen fanden es vielleicht nicht effizient, aber dies ist 100 besser als andere verfügbare Optionen.

Generieren Sie einen zufälligen Schlüssel und fügen Sie ihn in die Tabelle ein, um eine neue Zeile zu erstellen. Dann können Sie diesen Schlüssel verwenden, um den Primärschlüssel abzurufen. Verwenden Sie das Update, um Daten hinzuzufügen und andere Dinge zu tun.

Auf diese Weise können Sie eine Zeile sichern und den richtigen Primärschlüssel haben.

Ich empfehle dies wirklich nicht, es sei denn, Sie haben keine anderen Optionen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.