PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Valore di riferimento della colonna seriale in un'altra colonna durante lo stesso INSERT

È possibile utilizzare un CTE per recuperare il valore dalla sequenza una volta e usalo ripetutamente :

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

Il CTE con un comando di modifica dei dati richiede Postgres 9.1 o successivo.

Se non sei sicuro del nome della sequenza, usapg_get_serial_sequence() invece:

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

Se il nome della tabella "foo" potrebbe non essere univoco in tutti gli schemi nel database, qualificalo per lo schema. E se l'ortografia di un nome non è standard, devi virgolette:

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


Test rapidi hanno indicato l'idea di @Mark con lastval() potrebbe lavora anche tu:

INSERT INTO foo (ltree) VALUES ('1.' || lastval());
  • Puoi semplicemente lasciare id fuori dalla query, il serial la colonna verrà assegnata automaticamente. Non fa differenza.

  • Non dovrebbe esserci una race condition tra le righe. Cito il manuale:

currval

Restituisce il valore ottenuto più di recente da nextval per questa sequenza nella sessione corrente. (Viene segnalato un errore se nextval non è mai stato chiamato per questa sequenza in questa sessione.) Poiché restituisce un valore locale della sessione, fornisce una risposta prevedibile indipendentemente dal fatto che altre sessioni abbiano eseguito o meno nextval dalla sessione corrente.

Questa funzione richiede USAGE o SELECT privilegio sulla sequenza.

lastval

Restituisce l'ultimo valore restituito da nextval nella sessione corrente. Questa funzione è identica a currval , tranne che invece di prendere il nome della sequenza come argomento si riferisce a qualesequenza nextval è stato applicato più di recente nella sessione corrente. È un errore chiamare lastval se nextval non è stato ancora chiamato nella sessione corrente.

Questa funzione richiede USAGE o SELECT privilegio sull'ultima sequenza utilizzata.

Enfasi in grassetto la mia.

Ma , come ha commentato @Bernard, dopotutto può fallire:non vi è alcuna garanzia che il valore predefinito sia riempito (e nextval() chiamato nel processo) prima lastval() viene chiamato per riempire la seconda colonna ltree . Quindi attieniti alla prima soluzione e nextval() certo.