PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

PostgreSQL-Funktion für zuletzt eingefügte ID

( tl;dr :Gehe zu Option 3:INSERT mit RETURNING )

Denken Sie daran, dass es in Postgresql kein „id“-Konzept für Tabellen gibt, sondern nur Sequenzen (die normalerweise, aber nicht unbedingt als Standardwerte für Ersatzprimärschlüssel mit dem Pseudotyp SERIAL verwendet werden).

Wenn Sie daran interessiert sind, die ID einer neu eingefügten Zeile zu erhalten, gibt es mehrere Möglichkeiten:

Option 1:CURRVAL(<sequence name>); .

Zum Beispiel:

  INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
  SELECT currval('persons_id_seq');

Der Name der Sequenz muss bekannt sein, er ist wirklich willkürlich; In diesem Beispiel gehen wir davon aus, dass die Tabelle persons hat eine id mit dem SERIAL erstellte Spalte Pseudotyp. Um sich nicht darauf verlassen zu müssen und sich sauberer zu fühlen, können Sie stattdessen pg_get_serial_sequence verwenden :

  INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
  SELECT currval(pg_get_serial_sequence('persons','id'));

Achtung:currval() funktioniert nur nach einem INSERT (der nextval() ausgeführt hat ), in derselben Sitzung .

Möglichkeit 2:LASTVAL();

Dies ähnelt dem vorherigen, nur dass Sie den Sequenznamen nicht angeben müssen:Es sucht nach der zuletzt geänderten Sequenz (immer in Ihrer Sitzung, gleiche Einschränkung wie oben).

Sowohl CURRVAL und LASTVAL sind völlig gleichzeitig sicher. Das Verhalten der Sequenz in PG ist so ausgelegt, dass verschiedene Sitzungen nicht stören, sodass kein Risiko von Race-Conditions besteht (wenn eine andere Sitzung eine weitere Zeile zwischen meinem INSERT und meinem SELECT einfügt, erhalte ich immer noch meinen korrekten Wert).

Allerdings Sie haben ein subtiles potenzielles Problem. Wenn die Datenbank einen TRIGGER (oder eine REGEL) hat, wird beim Einfügen in persons Tabelle, macht einige zusätzliche Einfügungen in andere Tabellen ... dann LASTVAL wird uns wahrscheinlich den falschen Wert geben. Das Problem kann sogar mit CURRVAL auftreten , wenn die zusätzlichen Einfügungen in denselben persons vorgenommen werden Tabelle (dies ist viel seltener, aber das Risiko besteht immer noch).

Möglichkeit 3:INSERT mit RETURNING

INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;

Dies ist der sauberste, effizienteste und sicherste Weg, um die ID zu erhalten. Es hat keine der Risiken des vorherigen.

Nachteile? Fast keine:Möglicherweise müssen Sie die Art und Weise ändern, wie Sie Ihre INSERT-Anweisung aufrufen (im schlimmsten Fall erwartet Ihre API- oder DB-Schicht möglicherweise nicht, dass ein INSERT einen Wert zurückgibt). es ist kein Standard-SQL (wen interessiert das); es ist seit Postgresql 8.2 (Dezember 2006...) verfügbar

Fazit:Wenn Sie können, entscheiden Sie sich für Option 3. Ansonsten bevorzugen Sie 1.

Hinweis:Alle diese Methoden sind nutzlos, wenn Sie beabsichtigen, die zuletzt eingefügte ID global zu erhalten (nicht unbedingt durch Ihre Sitzung). Dazu müssen Sie auf SELECT max(id) FROM table zurückgreifen (Natürlich liest dies keine nicht festgeschriebenen Einfügungen von anderen Transaktionen).

Umgekehrt sollten Sie nie Verwenden Sie SELECT max(id) FROM table stattdessen eine der 3 Optionen oben, um die ID zu erhalten, die gerade von Ihrem INSERT generiert wurde -Anweisung, weil (abgesehen von der Leistung) dies nicht gleichzeitig sicher ist:zwischen Ihren INSERT und Ihr SELECT eine andere Sitzung könnte einen anderen Datensatz eingefügt haben.