Com o
select max(id) + 1
abordagem, duas sessões inseridas simultaneamente verão o mesmo ID máximo atual da tabela e ambas inserem o mesmo novo valor de ID. A única maneira de usar isso com segurança é bloquear a tabela antes de iniciar a transação, o que é doloroso e serializa as transações. (E como Stijn aponta, os valores podem ser reutilizados se o registro mais alto for excluído). Basicamente, nunca use essa abordagem. (Ocasionalmente, pode haver uma razão convincente para fazê-lo, mas não tenho certeza se já vi uma). A sequência garante que as duas sessões obterão valores diferentes e nenhuma serialização é necessária. Ele terá um desempenho melhor e será mais seguro, mais fácil de codificar e mais fácil de manter.
A única maneira de obter erros duplicados usando a sequência é se já existirem registros na tabela com IDs acima do valor da sequência ou se algo ainda estiver inserindo registros sem usar a sequência. Portanto, se você tivesse uma tabela existente com IDs inseridos manualmente, digamos de 1 a 10, e criasse uma sequência com um valor inicial de 1 padrão, a primeira inserção usando a sequência tentaria inserir um ID de 1 - que já existe . Depois de tentar isso 10 vezes, a sequência lhe daria 11, o que funcionaria. Se você usasse a abordagem max-ID para fazer a próxima inserção que usaria 12, mas a sequência ainda estaria em 11 e também forneceria 12 na próxima vez que você chamasse
nextval
. A sequência e a tabela não estão relacionadas. A sequência não é atualizada automaticamente se um valor de ID gerado manualmente for inserido na tabela, portanto, as duas abordagens não se misturam. (Entre outras coisas, a mesma sequência pode ser usada para gerar IDs para várias tabelas, conforme mencionado nos documentos).
Se você estiver mudando de uma abordagem manual para uma abordagem de sequência, precisará garantir que a sequência seja criada com um valor inicial maior do que todos os IDs existentes na tabela e que tudo o que faz uma inserção usa a sequência apenas no futuro.