(tl;dr
: goto Option 3: INSERT mit RÜCKKEHR)
Daran erinnern, dass in postgresql es keine „id“ -Konzept ist für Tabellen, nur Sequenzen (die in der Regel, aber nicht notwendigerweise als Standardwerte für Surrogat verwendet Primärschlüssel mit dem Pseudotyp SERIAL).
Wenn Sie sich für die ID eines neu eingefügten Zeile interessiert sind, 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 bekannt sein müssen, es ist wirklich willkürlich; In diesem Beispiel nehmen wir an, dass die Tabelle persons
eine id
-Spalte hat, die mit dem Pseudotyp SERIAL
erstellt wurde. Um zu vermeiden, auf diese zu verlassen und mehr sauber 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'));
Caveat: currval()
funktioniert nur nach einem INSERT
(die nextval()
hat ausgeführt), in der gleichen Sitzung.
Option 2: LASTVAL();
Dies ist ähnlich dem vorherigen, nur dass Sie die Sequenznummer nicht angeben müssen: es für das letzte modifizierte Sequenz sieht (immer in Ihrer Sitzung, gleiche Einschränkung wie oben).
Beide CURRVAL
und LASTVAL
sind völlig gleichzeitig sicher. Das Verhalten der Sequenz in PG ist so ausgelegt, dass unterschiedliche Sessions nicht stören, also besteht kein Risiko von Race Conditions (wenn eine andere Session eine andere Zeile zwischen meinem INSERT und meinem SELECT einfügt, bekomme ich immer noch meinen korrekten Wert).
Allerdings sie haben ein subtiles potenzielles Problem. Wenn die Datenbank einige TRIGGER (oder RULE) hat, die beim Einfügen in persons
Tabelle, einige zusätzliche Einfügungen in anderen Tabellen macht ... dann LASTVAL
wird uns wahrscheinlich den falschen Wert geben.Das Problem kann sogar passieren mit CURRVAL
, wenn die zusätzlichen Einfügungen in die gleiche Tabelle persons
getan werden (das ist viel weniger üblich, aber das Risiko besteht immer noch).
Option 3: INSERT
mit RETURNING
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;
Dies ist der saubere, effizienter und sicherer Weg, um die ID zu bekommen. Es hat keine der Risiken des vorherigen.
Nachteile? Fast keine: Möglicherweise müssen Sie die Art ä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 verfügbar seit Postgresql 8.2 (Dezember 2006 ...)
Fazit: Wenn Sie, 3. In anderen Ländern für die Option gehen, bevorzugt 1.
Hinweis: All diese Methoden sind nutzlos, wenn Sie beabsichtigen, get die letzte global eingefügte ID (nicht unbedingt in Ihrer Sitzung). Dazu müssen Sie auf select max(id) from table
zurückgreifen (natürlich werden nicht festgeschriebene Einfügungen aus anderen Transaktionen nicht gelesen).
@a_horse_with_no_name zu verwenden, wird es auf diese Weise nicht funktionieren. Für beide Kinder benötige ich den gleichen Wert von 'PARENT_ID', beide Funktionen geben mir das Neueste. – Opal