tenho uma tabela:
CREATE TABLE names (id serial, name varchar(20))
Eu quero o "último id inserido" dessa tabela, sem usar RETURNING id
na inserção. Parece haver uma função CURRVAL()
, mas não entendo como usá-la.
Eu tentei com:
SELECT CURRVAL() AS id FROM names_id_seq
SELECT CURRVAL('names_id_seq')
SELECT CURRVAL('names_id_seq'::regclass)
mas nenhum deles funciona. Como posso usar currval()
para obter o último id inserido?
Isso é direto do Stack Overflow
Como foi apontado por @a_horse_with_no_name e @Jack Douglas, currval funciona apenas com a sessão atual. Portanto, se você concorda com o fato de que o resultado pode ser afetado por uma transação não confirmada de outra sessão e ainda deseja algo que funcione nas sessões, pode usar isto:
Use o link para SO para obter mais informações.
A partir da documentação do Postgres, porém, é claramente afirmado que
Então, estritamente falando, para usar corretamente currval ou last_value para uma sequência entre sessões, você precisaria fazer algo assim?
Assumindo, claro, que você não terá um insert ou qualquer outra forma de usar o campo serial na sessão atual.
Se você criar uma coluna como
serial
PostgreSQL cria automaticamente uma sequência para isso.O nome da sequência é gerado automaticamente e é sempre tablename_columnname_seq, no seu caso a sequência será names
names_id_seq
.Depois de inserir na tabela, você pode chamar
currval()
com esse nome de sequência:Em vez de codificar o nome da sequência, você também pode usar
pg_get_serial_sequence()
:Dessa forma, você não precisa depender da estratégia de nomenclatura que o Postgres usa.
Ou se você não quiser usar o nome da sequência, use
lastval()
Você precisa chamar
nextval
essa sequência nesta sessão antescurrval
:então você não pode encontrar o 'último id inserido' da sequência, a menos que
insert
seja feito na mesma sessão (uma transação pode reverter, mas a sequência não)como apontado na resposta de a_horse,
create table
com uma coluna do tiposerial
criará automaticamente uma sequência e a usará para gerar o valor padrão para a coluna, portanto,insert
normalmente acessanextval
implicitamente:Portanto, há alguns problemas com esses vários métodos:
Currval só pega o último valor gerado na sessão atual - o que é ótimo se você não tiver mais nada gerando valores, mas nos casos em que você pode chamar um trigger e/ou ter a sequência avançada mais de uma vez na transação atual é não vai retornar o valor correto. Isso não é um problema para 99% das pessoas lá fora - mas é algo que se deve levar em consideração.
A melhor maneira de obter o identificador exclusivo atribuído após uma operação de inserção é usando a cláusula RETURNING. O exemplo abaixo assume que a coluna vinculada à sequência é chamada de "id":
Observe que a utilidade da cláusula RETURNING vai muito além de apenas obter a sequência, pois ela também:
Retorne os valores que estavam sendo excluídos:
delete da tabela A onde id > 100 retornando *
Retorne as linhas modificadas após um UPDATE:
atualizar tabela Um conjunto X='y' onde blah='blech' retornando *
Use o resultado de uma exclusão para uma atualização:
WITH A as (excluir * da tabela A como id de retorno) atualizar B set delete=true onde id in (selecionar id de A);
No PostgreSQL 11.2 você pode tratar a sequência como uma tabela que parece:
Exemplo se você tiver uma sequência chamada: 'names_id_seq'
Isso deve fornecer o último id inserido (4 neste caso), o que significa que o valor atual (ou o valor que deve ser usado para o próximo id) deve ser 5.
Eu tive que executar uma consulta apesar de usar SQLALchemy porque não consegui usar currval.
Este foi um projeto de frasco python + postgresql.
Se você quiser obter o valor das sequências sem ter chamado
nextval()
, e sem ter que modificar a sequência, montei uma função PL/pgSQL para lidar com isso: Encontre o valor de todas as sequências do banco de dadosVocê precisa
GRANT
usar no esquema, assim:e
Diferentes versões do PostgreSQL podem ter funções diferentes para obter o ID de sequência atual ou seguinte.
Primeiro, você precisa saber a versão do seu Postgres. Usando select version(); para obter a versão.
No PostgreSQL 8.2.15, você obtém o id de sequência atual usando
select last_value from schemaName.sequence_name
.Se a declaração acima não funcionar, você pode usar
select currval('schemaName.sequence_name');