Encontrei o problema de que minha sequência de chaves primárias não está sincronizada com as linhas da minha tabela.
Ou seja, quando insiro uma nova linha, recebo um erro de chave duplicada porque a sequência implícita no tipo de dados serial retorna um número que já existe.
Parece ser causado pela importação / restauração que não mantém a sequência corretamente.
postgresql
primary-key
database-sequence
meleyal
fonte
fonte
Respostas:
Fonte - Fórum Ruby
fonte
SELECT setval('your_table_id_seq', coalesce((select max(id)+1 from your_table), 1), false);
SELECT setval('your_seq',(SELECT GREATEST(MAX(your_id)+1,nextval('your_seq'))-1 FROM your_table))
pg_get_serial_sequence
pode ser usado para evitar suposições incorretas sobre o nome da sequência. Isso redefine a sequência de uma vez:Ou, mais concisamente:
No entanto, este formulário não pode manipular tabelas vazias corretamente, pois max (id) é nulo, e você também não pode definir o valor 0 porque estaria fora do intervalo da sequência. Uma solução alternativa para isso é recorrer à
ALTER SEQUENCE
sintaxe ieMas
ALTER SEQUENCE
é de uso limitado, porque o nome da sequência e o valor de reinicialização não podem ser expressões.Parece que a melhor solução para todos os fins é chamar
setval
false com o terceiro parâmetro, permitindo especificar o "próximo valor a ser usado":Isso marca todas as minhas caixas:
Por fim, observe que
pg_get_serial_sequence
só funciona se a sequência pertencer à coluna. Este será o caso se a coluna de incremento tiver sido definida como umserial
tipo, no entanto, se a sequência foi adicionada manualmente, é necessário garantir queALTER SEQUENCE .. OWNED BY
também seja realizada.ou seja, se o
serial
tipo foi usado para a criação da tabela, tudo deve funcionar:Mas se as sequências foram adicionadas manualmente:
fonte
setval()
define o valor atual enextval()
já retornará o valor atual +1.A maneira mais curta e rápida :
tbl_id
sendo aserial
coluna da tabelatbl
, desenhando a partir da sequênciatbl_tbl_id_seq
(que é o nome automático padrão).Se você não souber o nome da sequência anexada (que não precisa estar no formato padrão), use
pg_get_serial_sequence()
:Não há erro de um por um aqui. Por documentação:
Negrito ênfase minha.
Se a tabela puder estar vazia e realmente começar a partir de 1 neste caso:
Não podemos simplesmente usar o formulário com 2 paremater e começar
0
porque o limite inferior das seqüências é 1 por padrão (a menos que seja personalizado).Concorrência
Ainda não há defesa contra a atividade de sequência simultânea ou gravações na tabela nas consultas acima. Se isso for relevante, você pode bloquear a tabela no modo exclusivo. Isso evita que as transações simultâneas gravem um número mais alto enquanto você tenta sincronizar. (Ele também bloqueia temporariamente gravações inofensivas que não mexem com o número máximo.)
Mas não leva em conta os clientes que podem ter buscado números de sequência antecipadamente sem nenhum bloqueio na tabela principal (o que pode acontecer). Para permitir isso, também, apenas aumente o valor atual da sequência, nunca o diminua. Pode parecer paranóico, mas isso está de acordo com a natureza das seqüências e a defesa contra problemas de concorrência.
fonte
EXECUTE format()
(como @ EB.'s) é uma função essencial! Como corrigir essa falta de biblioteca padrão no PostgreSQL ????Isso redefinirá todas as seqüências do público, sem suposições sobre nomes de tabelas ou colunas. Testado na versão 8.4
fonte
substring(column_default, '''(.*)''')
vez detable_name || '_' || column_name || '_seq'
. Funciona perfeitamente.quote_literal
equote_ident
, ou de preferência aformat
função, devem realmente ser usadas aqui.substring(column_default from 'nextval\(''(.+)''::regclass\)')
pegar explicitamente o nome da sequência. Funcionou como um encanto.substring(column_default, '''(.*)''') instead of table_name || '_' || column_name || '_seq'
ALTER SEQUENCE nome_da_seção RESTART WITH (SELECT max (id) FROM nome_tabela);Não funcionaCopiado da resposta @tardate:
fonte
Este comando apenas altera o valor da sequência de chaves gerada automaticamente no postgresql
No lugar de zero, você pode colocar qualquer número a partir do qual deseja reiniciar a sequência.
o nome da sequência padrão será
"TableName_FieldName_seq"
. Por exemplo, se o nome da tabela for"MyTable"
e o nome do campo"MyID"
, o nome da sequência será"MyTable_MyID_seq"
.Esta é a resposta é a mesma que a resposta de @ murugesanponappan, mas há um erro de sintaxe em sua solução. você não pode usar a subconsulta
(select max()...)
noalter
comando. Para que você precise usar um valor numérico fixo ou precise usar uma variável no lugar da subconsulta.fonte
Redefina todas as seqüências, sem suposições sobre nomes, exceto que a chave primária de cada tabela é "id":
fonte
pg_get_serial_sequence(''"' || tablename || '"''
EXECUTE format( 'SELECT setval(pg_get_serial_sequence(%L, %L), coalesce(max(id),0) + 1, false) FROM %I;', $1,$2,$1 );
Essas funções estão repletas de perigos quando nomes de sequências, nomes de colunas, nomes de tabelas ou esquemas possuem caracteres engraçados, como espaços, sinais de pontuação e similares. Eu escrevi isso:
Você pode chamá-lo para uma única sequência, passando o OID para ele e retornará o número mais alto usado por qualquer tabela que tenha a sequência como padrão; ou você pode executá-lo com uma consulta como esta, para redefinir todas as seqüências no seu banco de dados:
Usando uma qual diferente, você pode redefinir apenas a sequência em um determinado esquema e assim por diante. Por exemplo, se você deseja ajustar sequências no esquema "público":
Observe que, devido à forma como setval () funciona, você não precisa adicionar 1 ao resultado.
Como observação final, tenho que avisar que alguns bancos de dados parecem ter padrões vinculados a sequências de maneiras que não permitem que os catálogos do sistema tenham informações completas sobre eles. Isso acontece quando você vê coisas assim no \ d do psql:
Observe que a chamada nextval () nessa cláusula padrão possui uma conversão de :: texto além da conversão de :: regclass. Eu acho que isso se deve a bancos de dados sendo pg_dump'ed de versões antigas do PostgreSQL. O que acontecerá é que a função sequence_max_value () acima ignorará essa tabela. Para corrigir o problema, você pode redefinir a cláusula DEFAULT para se referir à sequência diretamente sem a conversão:
Em seguida, o psql o exibe corretamente:
Assim que você tiver corrigido isso, a função funcionará corretamente para esta tabela e para todas as outras que possam usar a mesma sequência.
fonte
newmax := r.max::bigint;
para fazê-la funcionar corretamente para mim.'SELECT max(' || quote_ident(colname) || ') FROM '
=>'SELECT max(' || quote_ident(colname) || '::bigint) FROM '
observe o::bigint
elenco adicionado na consulta de construção dinâmica.Outro plpgsql - redefine apenas se
max(att) > then lastval
comentar também a linha
--execute format('alter sequence
fornecerá a lista, não redefinindo o valorfonte
Redefinir toda a sequência de public
fonte
Eu sugiro esta solução encontrada no wiki do postgres. Ele atualiza todas as seqüências de suas tabelas.
Como usar (do wiki do postgres):
Exemplo:
Artigo original (também com correção para propriedade da sequência) aqui
fonte
Algumas respostas realmente graves aqui, suponho que costumava ser muito ruim na época em que isso foi solicitado, pois muitas respostas daqui não funcionam para a versão 9.3. A documentação desde a versão 8.0 fornece uma resposta para esta mesma pergunta:
Além disso, se você precisar cuidar de nomes de sequência com distinção entre maiúsculas e minúsculas, é assim que você faz:
fonte
Esse problema ocorre comigo ao usar a estrutura da entidade para criar o banco de dados e, em seguida, propagar o banco de dados com dados iniciais, o que torna a sequência incompatível.
Eu o resolvi criando um script para ser executado após a propagação do banco de dados:
fonte
MAX("Id") + 1
que funciona melhor para mim quando a sequência é = ao máximo.Minha versão usa a primeira, com alguma verificação de erro ...
fonte
RAISE WARNING
identificou para mim.Juntando tudo
irá corrigir a
id'
sequência da tabela especificada (como geralmente é necessário no django, por exemplo).fonte
antes, eu ainda não havia tentado o código: a seguir, eu posto a versão do código sql para as soluções Klaus e user457226 que funcionavam no meu pc [Postgres 8.3], com apenas alguns pequenos ajustes para o Klaus e para a minha versão para o usuário457226.
Solução Klaus:
solução user457226:
fonte
Verifique novamente toda a sequência na função de esquema pública
fonte
Para reiniciar toda a sequência para 1, use:
fonte
A resposta do Klaus é a mais útil e executada para uma pequena falha: você precisa adicionar DISTINCT na instrução select.
No entanto, se você tiver certeza de que nenhum nome de tabela + coluna pode ser equivalente a duas tabelas diferentes, também poderá usar:
que é uma extensão da solução user457226 para o caso em que algum nome de coluna interessado não seja 'ID'.
fonte
Se você vir esse erro ao carregar dados SQL personalizados para inicialização, outra maneira de evitar isso é:
Em vez de escrever:
Remova a
id
(chave primária) dos dados iniciaisIsso mantém a sequência do Postgres sincronizada!
fonte
Esta resposta é uma cópia do mauro.
fonte
Passei uma hora tentando fazer com que a resposta do djsnowsill funcionasse com um banco de dados usando tabelas e colunas de casos mistos, e finalmente encontrei a solução graças a um comentário de Manuel Darveau, mas achei que poderia deixar isso mais claro para todos:
Isso tem o benefício de:
Para explicar, o problema era que são
pg_get_serial_sequence
necessárias seqüências de caracteres para descobrir o que você está se referindo; portanto, se você fizer:Isso é conseguido usando
''%1$I''
a string format,''
faz com que um apóstrofo1$
signifique primeiro argumento eI
entre aspasfonte
fonte
Hack feio para consertá-lo usando alguma mágica de shell, não é uma ótima solução, mas pode inspirar outras pessoas com problemas semelhantes :)
fonte
Tente reindexar .
ATUALIZAÇÃO: Como apontado nos comentários, isso foi uma resposta à pergunta original.
fonte
SELECT setval...
faz o JDBC bork, então aqui está uma maneira compatível com Java de fazer isso:fonte
Um método para atualizar todas as sequências em seu esquema usadas como um ID:
fonte
Basta executar o comando abaixo:
fonte
Há muitas boas respostas aqui. Eu tive a mesma necessidade depois de recarregar meu banco de dados Django.
Mas eu precisava:
Parece uma necessidade muito semelhante à solicitada pelo original.
Graças a Baldiry e Mauro me colocou no caminho certo.
Em seguida, execute e veja as alterações executadas:
Devoluções
fonte