(
tl;dr :vá para a opção 3:INSERT com RETURNING ) Lembre-se que no postgresql não existe um conceito de "id" para tabelas, apenas sequências (que são normalmente, mas não necessariamente, usados como valores padrão para chaves primárias substitutas, com o pseudotipo SERIAL).
Se você estiver interessado em obter o id de uma linha recém-inserida, existem várias maneiras:
Opção 1:
CURRVAL(<sequence name>); . Por exemplo:
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval('persons_id_seq');
O nome da sequência deve ser conhecido, é realmente arbitrário; neste exemplo, assumimos que a tabela
persons tem um id coluna criada com o SERIAL pseudo-tipo. Para evitar depender disso e se sentir mais limpo, você pode usar pg_get_serial_sequence : INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval(pg_get_serial_sequence('persons','id'));
Advertência:
currval() só funciona após um INSERT (que executou nextval() ), na mesma sessão . Opção 2:
LASTVAL(); Isso é semelhante ao anterior, só que você não precisa especificar o nome da sequência:ele procura a sequência modificada mais recente (sempre dentro de sua sessão, mesma ressalva acima).
Ambos
CURRVAL e LASTVAL são totalmente seguros simultâneos. O comportamento da sequência no PG é projetado para que sessões diferentes não interfiram, para que não haja risco de condições de corrida (se outra sessão inserir outra linha entre meu INSERT e meu SELECT, ainda recebo meu valor correto). No entanto eles têm um problema potencial sutil. Se o banco de dados possui algum TRIGGER (ou RULE) que, ao ser inserido em
persons tabela, faz algumas inserções extras em outras tabelas... então LASTVAL provavelmente nos dará o valor errado. O problema pode até acontecer com CURRVAL , se as inserções extras forem feitas nas mesmas persons tabela (isso é muito menos usual, mas o risco ainda existe). Opção 3:
INSERT com RETURNING INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;
Esta é a maneira mais limpa, eficiente e segura de obter o id. Não tem nenhum dos riscos do anterior.
Desvantagens? Quase nenhum:você pode precisar modificar a maneira como chama sua instrução INSERT (na pior das hipóteses, talvez sua API ou camada de banco de dados não espere que um INSERT retorne um valor); não é SQL padrão (quem se importa); está disponível desde o Postgresql 8.2 (dezembro de 2006...)
Conclusão:Se puder, vá para a opção 3. Em outros lugares, prefira a 1.
Observação:todos esses métodos são inúteis se você pretende obter o último id inserido globalmente (não necessariamente pela sua sessão). Para isso, você deve recorrer a
SELECT max(id) FROM table (claro, isso não lerá inserções não confirmadas de outras transações). Por outro lado, você nunca use
SELECT max(id) FROM table em vez de uma das 3 opções acima, para obter o id gerado pelo seu INSERT declaração, porque (além do desempenho) isso não é seguro concorrente:entre seu INSERT e seu SELECT outra sessão pode ter inserido outro registro.