Uma maneira de referenciar o ID em uma transação de inserção múltipla? (postgres)

8

Supondo que a tabela "entity.eid" seja incrementada automaticamente, desejo poder fazer referência ao valor de incremento automático atribuído posteriormente na mesma transação. O jeito que eu tenho feito isso é fazendo várias transações, o que eu acho que não é o ideal.

START TRANSACTION;
INSERT INTO entity ...;
INSERT INTO t2 (eid, ...) VALUES (?NEW EID REF HERE?, ...), (...), (...);
COMMIT;
Tony
fonte

Respostas:

11

Existem diferentes maneiras de fazer isso.

A maneira mais fácil é usar a lastval()função que retornará o valor gerado pela "última" sequência nextval.

START TRANSACTION;
INSERT INTO entity ...;
INSERT INTO t2 (eid, ...) VALUES (lastval(), ...), (...), (...);
COMMIT;

Se você souber o nome da sequência para a entitytabela, também poderá usar a currvalfunção:

START TRANSACTION;
INSERT INTO entity ...;
INSERT INTO t2 (eid, ...) VALUES (currval('entity_eid_seq'), ...), (...), (...);
COMMIT;

Isso pode ser escrito de uma maneira mais geral, usando a pg_get_serial_sequence()função, evitando codificar o nome da sequência:

START TRANSACTION;
INSERT INTO entity ...;
INSERT INTO t2 (eid, ...) VALUES (currval(pg_get_serial_sequence('entity', 'eid')), ...), (...);
COMMIT;

Para mais detalhes, consulte o manual: http://www.postgresql.org/docs/current/static/functions-sequence.html

um cavalo sem nome
fonte
7

Você não especifica sua versão do Postgresql, mas se estiver usando o 8.4+, poderá usar a RETURNINGcláusula para retornar o ID (ou qualquer coluna) que acabou de ser inserido.

Documentos: http://www.postgresql.org/docs/current/static/sql-insert.html

Exemplo:

INSERT INTO t2 (eid, ...) VALUES (...) RETURNING eid;

Se você estiver usando o Postgresql versão 9.1+, também poderá usar as WITHcláusulas (aka Common Table Expressions) para inserir uma cláusula, em seguida, referenciar os valores da RETURNINGcláusula para executar mais ações (as cláusulas WITH podem ser encadeadas).

Documentos sobre a WITHcláusula: http://www.postgresql.org/docs/current/static/queries-with.html

bma
fonte
4

Vale a pena notar que SERIAL no Postgres é apenas uma INT com uma SEQUENCE como o valor padrão; você pode facilmente consultar o seqüenciador em uma transação, em vez de inserir na tabela permitindo que o padrão aconteça.

xenoterracida
fonte