O Postgres altera manualmente a sequência


189

Estou tentando definir uma sequência para um valor específico.

SELECT setval('payments_id_seq'), 21, true

Isso dá um erro:

ERROR: function setval(unknown) does not exist

Usar ALTER SEQUENCEtambém não parece funcionar?

ALTER SEQUENCE payments_id_seq LASTVALUE 22

Como isso pode ser feito?

Ref: https://www.postgresql.org/docs/current/static/functions-sequence.html


4
Parece que setval()tem pelo menos dois argumentos.

Respostas:


262

Os parênteses estão fora do lugar:

SELECT setval('payments_id_seq', 21, true);  # next value will be 22

Caso contrário, você está ligando setvalcom um único argumento, enquanto isso requer dois ou três.


2
O que o último argumento "verdadeiro" significa?
inafalcao 27/09

15
truesignifica que o próximo valor será o número fornecido + 1, neste caso 22. falsesignifica que o próximo valor será o número fornecido, ou 21. Por padrão, setval se comportará como se tivesse truesido escolhido. Mais detalhes: postgresql.org/docs/9.6/static/functions-sequence.html
Tom Mertz

1
uma vantagem da select setvalsintaxe alter sequenceé que você pode usar consultas aninhadas, por exemplo, para select max(id) from payments.
Mariotomo 11/07/19

187

Esta sintaxe não é válida em nenhuma versão do PostgreSQL:

ALTER SEQUENCE payments_id_seq LASTVALUE 22

Isso funcionaria:

ALTER SEQUENCE payments_id_seq RESTART WITH 22;

e é equivalente a:

SELECT setval('payments_id_seq', 22, FALSE);

Mais no manual atual para funçõesALTER SEQUENCE e sequência .

Observe que setval()espera um (regclass, bigint)ou (regclass, bigint, boolean). No exemplo acima, estou fornecendo literais sem tipo . Isso também funciona. Mas se você alimentar variáveis ​​digitadas para a função, poderá precisar de conversão explícita de tipos para satisfazer a resolução do tipo de função. Gostar:

SELECT setval(my_text_variable::regclass, my_other_variable::bigint, FALSE);

Para operações repetidas, você pode estar interessado em:

ALTER SEQUENCE payments_id_seq START WITH 22; -- set default
ALTER SEQUENCE payments_id_seq RESTART;       -- without value

START [WITH]armazena um RESTARTnúmero padrão , usado para RESTARTchamadas subseqüentes sem valor. Você precisa do Postgres 8.4 ou posterior para a última parte.


4
ALTER SEQUENCE [sequence] RESTART WITH (SELECT MAX(col) from table);não funciona, enquanto SELECT setval('sequence', (SELECT (MAX(col) from table), TRUE);que funciona. Eu recebo um erro de sintaxe. (Postgres 9.4)
NuclearPeon

1
Nenhuma subconsulta permitida em um comando DDL ("comando utilitário"). Veja: stackoverflow.com/a/36025963/939860
Erwin Brandstetter

1
@MitalPritmani: Você pode precisar de conversão de tipos. Considere as instruções adicionadas acima.
Erwin Brandstetter

1
@NuclearPeon Eu acho que você quer dizer, SELECT setval('sequence', (SELECT MAX(col) from table), TRUE);caso contrário, seus parênteses não se alinham.
dland 19/03/19

1
@dland: Lado: equivalente mais curto e mais rápido: SELECT setval('seq', max(col)) FROM tbl;Veja: stackoverflow.com/a/23390399/939860
Erwin Brandstetter

33

Usar select setval('payments_id_seq', 21, true);

setval contém 3 parâmetros:

  • 1º parâmetro é sequence_name
  • O segundo parâmetro é Next nextval
  • O terceiro parâmetro é opcional.

O uso de true ou false no terceiro parâmetro de setval é o seguinte:

SELECT setval('payments_id_seq', 21);           // Next nextval will return 22
SELECT setval('payments_id_seq', 21, true);     // Same as above 
SELECT setval('payments_id_seq', 21, false);    // Next nextval will return 21

A melhor maneira de evitar a codificação do nome da sequência, o valor da próxima sequência e o tratamento correto da tabela de colunas vazias, você pode usar da seguinte maneira:

SELECT setval(pg_get_serial_sequence('table_name', 'id'), coalesce(max(id), 0)+1 , false) FROM table_name;

onde table_nameé o nome da tabela, idé o primary keyda tabela


Obrigado! Última expressão é exatamente o que eu estava procurando. Permite-me reservar os valores da sequência para inserir posteriormente por lote.
Timur


0

Não tento alterar a sequência via setval. Mas usando ALTERI foi emitido como escrever o nome da sequência corretamente. E isso só funciona para mim:

  1. Verifique o nome da sequência necessária usando SELECT * FROM information_schema.sequences;

  2. ALTER SEQUENCE public."table_name_Id_seq" restart {number};

    No meu caso foi ALTER SEQUENCE public."Services_Id_seq" restart 8;

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.