Pode CURRENT_TIMESTAMP
ser usado como um PRIMARY KEY
?
Existe a possibilidade de dois ou mais INSERTs diferentes obterem o mesmo CURRENT_TIMESTAMP
?
Pode CURRENT_TIMESTAMP
ser usado como um PRIMARY KEY
?
Existe a possibilidade de dois ou mais INSERTs diferentes obterem o mesmo CURRENT_TIMESTAMP
?
Respostas:
Conforme a documentação , a precisão do CURRENT_TIMESTAMP
é microssegundos. Assim, a probabilidade de uma colisão é baixa, mas possível.
Agora imagine um bug que acontece muito raramente e causa erros no banco de dados. Quão difícil é depurá-lo? É um bug muito pior do que um que é pelo menos determinístico.
O contexto mais amplo: você provavelmente deseja evitar essas pequenas nuances com as seqüências, o que é particularmente irritante se você está acostumado ao MySQL.
Além disso, se você estiver usando transações (a maioria das estruturas da Web, principalmente as de Java, fazem!), Os carimbos de data e hora serão os mesmos dentro de uma transação! Uma demonstração:
postgres=# begin;
BEGIN
postgres=# select current_timestamp;
current_timestamp
-------------------------------
2018-08-06 02:41:42.472163+02
(1 Zeile)
postgres=# select current_timestamp;
current_timestamp
-------------------------------
2018-08-06 02:41:42.472163+02
(1 Zeile)
Até logo? Duas seleções, exatamente o mesmo resultado. Eu não digito tão rápido. ;-)
-
Se você quiser IDs com facilidade, evitando o uso das seqüências, gere algum valor de hash a partir dos identificadores reais dos registros. Por exemplo, se seu banco de dados possui seres humanos e você sabe que a data de nascimento, o nome de solteira da mãe e o nome real os identificam exclusivamente, use um
md5(mother_name || '-' || given_name || '-' birthday);
como id. Além disso, você pode usar uma CreationDate
coluna, depois do que indexa a tabela, mas não é uma chave (que é o ID).
Ps Em geral, é uma prática muito boa tornar seu banco de dados tão determinístico quanto possível. Ou seja, a mesma operação deve criar exatamente a mesma alteração no banco de dados . Qualquer identificação baseada em carimbo de data e hora falha neste recurso importante. E se você quiser depurar ou simular alguma coisa? Você reproduz uma operação e o mesmo objeto será criado com um ID diferente ... não é realmente difícil de seguir e poupa muitas horas de trabalho.
Ps2 Qualquer pessoa que verifique seu código no futuro não terá a melhor opinião para ver os IDs gerados por carimbo de data / hora, pelos motivos acima.
INSERT
de várias linhas, todas elas serão iguais current_timestamp
. E então você tem gatilhos ...
Na verdade, não é porque é possível que CURRENT_TIMESTAMP forneça dois valores idênticos para dois INSERTs subsequentes (ou um único INSERT com várias linhas).
Use um UUID baseado em tempo: uuid_generate_v1mc () .
Estritamente falando: Não. Porque CURRENT_TIMESTAMP
é uma função e apenas uma ou mais colunas da tabela podem formar uma PRIMARY KEY
restrição.
Se você deseja criar uma PRIMARY KEY
restrição em uma coluna com o valor padrão CURRENT_TIMESTAMP
, a resposta é: Sim, você pode . Nada o impede de fazê-lo, como nada o impede de atirar maçãs da cabeça do seu filho. A questão ainda não faria sentido enquanto você não definir seu objetivo. Que tipo de dados a coluna e a tabela devem conter? Quais regras você está tentando implementar?
Normalmente, a ideia é executada com erros de chave duplicados, pois CURRENT_TIMESTAMP
é uma STABLE
função que retorna o mesmo valor para a mesma transação (a hora de início da transação). Vários INSERTs na mesma transação são obrigados a colidir - como outras respostas já ilustradas. O manual:
Como essas funções retornam a hora de início da transação atual, seus valores não mudam durante a transação. Isso é considerado um recurso: a intenção é permitir que uma única transação tenha uma noção consistente do horário "atual", para que várias modificações na mesma transação tenham o mesmo carimbo de hora.
Os carimbos de data e hora do Postgres são implementados como números inteiros de 8 bytes, representando até 6 dígitos fracionários (resolução de microssegundos).
Se você está construindo uma tabela que é suposto não detêm mais de uma linha por microssegundo e essa condição não vai mudar (algo chamado sensor_reading_per_microsecond
), então pode fazer sentido. Linhas duplicadas devem gerar um erro de violação de chave duplicada. Essa é uma exceção exótica, no entanto. E o tipo de dados timestamptz
(não timestamp
) provavelmente seria preferível. Vejo:
Eu ainda preferiria usar uma chave primária serial substituta. E adicione uma UNIQUE
restrição na coluna de carimbo de data / hora. Menos complicações possíveis, sem depender dos detalhes de implementação do RDBMS.
sensor_reading_per_microsecond
pode colidir se você não puder garantir absolutamente que o tempo de cada leitura esteja perfeitamente sincronizado em relação à anterior; um desvio de microssegundo (que geralmente não é impossível) interrompe o esquema. Em geral, eu ainda evitaria isso totalmente. (Lembre-se, como você indicou, nesse caso, a colisão resultante pode ser desejável!)