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

Referenzwert einer seriellen Spalte in einer anderen Spalte während desselben INSERT

Sie könnten einen CTE verwenden, um den Wert aus der Sequenz einmal abzurufen und verwenden Sie es wiederholt :

WITH cte AS (
   SELECT nextval('foo_id_seq') AS id
   )
INSERT INTO foo (id, ltree)
SELECT id, '1.' || id
FROM   cte;

Der CTE mit einem Datenänderungsbefehl erfordert Postgres 9.1 oder höher.

Wenn Sie sich über den Namen der Sequenz nicht sicher sind, verwenden Sie pg_get_serial_sequence() stattdessen:

WITH i AS (
   SELECT nextval(pg_get_serial_sequence('foo', 'id')) AS id
   )
INSERT INTO foo (id, ltree)
SELECT id, '1.' || id
FROM   i;

Wenn der Tabellenname „foo“ möglicherweise nicht über alle Schemas in der Datenbank hinweg eindeutig ist, qualifizieren Sie ihn als Schema. Und wenn die Schreibweise eines Namens nicht dem Standard entspricht, müssen Sie doppelte Anführungszeichen setzen:

pg_get_serial_sequence('"My_odd_Schema".foo', 'id')


Schnelltests zeigten @Marks Idee mit lastval() an vielleicht funktioniert auch:

INSERT INTO foo (ltree) VALUES ('1.' || lastval());
  • Sie können einfach id hinterlassen aus der Abfrage die serial Spalte wird automatisch zugewiesen. Macht keinen Unterschied.

  • Es sollte keine Racebedingung zwischen Zeilen geben. Ich zitiere das Handbuch:

currval

Gibt den zuletzt von nextval erhaltenen Wert zurück für diese Sequenz in der aktuellen Sitzung. (Ein Fehler wird gemeldet, wenn nextval wurde für diese Sequenz in dieser Sitzung noch nie aufgerufen.) Da dies einen sitzungslokalen Wert zurückgibt, gibt es eine vorhersagbare Antwort, ob andere Sitzungen nextval ausgeführt haben oder nicht seit der aktuellen Sitzung.

Diese Funktion erfordert USAGE oder SELECT Privileg für die Sequenz.

lastval

Gibt den zuletzt von nextval zurückgegebenen Wert zurück in der aktuellen Sitzung. Diese Funktion ist identisch mit currval , außer Anstatt den Sequenznamen als Argument zu verwenden, bezieht es sich auf die beliebige Sequenz nextval zuletzt in der aktuellen Sitzung angewendet wurde. Es ist ein Fehler, lastval aufzurufen wenn nextval wurde in der aktuellen Sitzung noch nicht aufgerufen.

Diese Funktion erfordert USAGE oder SELECT Privileg auf die zuletzt verwendete Sequenz.

Fettdruck von mir.

Aber , wie @Bernard kommentierte, kann es doch fehlschlagen:Es gibt keine Garantie dafür, dass der Standardwert gefüllt ist (und nextval() dabei aufgerufen) vorher lastval() wird aufgerufen, um die 2. Spalte ltree zu füllen . Bleiben Sie also bei der ersten Lösung und nextval() sicher sein.