Se CURRENT_TIMESTAMP
puede utilizar como PRIMARY KEY
?
¿Existe la posibilidad de que dos o más INSERTs diferentes obtengan lo mismo CURRENT_TIMESTAMP
?
Se CURRENT_TIMESTAMP
puede utilizar como PRIMARY KEY
?
¿Existe la posibilidad de que dos o más INSERTs diferentes obtengan lo mismo CURRENT_TIMESTAMP
?
Respuestas:
Según la documentación , la precisión de los CURRENT_TIMESTAMP
microsegundos. Por lo tanto, la probabilidad de una colisión es baja, pero posible.
Ahora imagine un error que ocurre muy raramente y causa errores en la base de datos. ¿Qué tan difícil es depurarlo? Es un error mucho peor que uno que es al menos determinista.
El contexto más amplio: probablemente desee evitar estos pequeños matices con las secuencias, lo cual es particularmente molesto si está acostumbrado a MySQL.
Además, si está utilizando transacciones (¡la mayoría de los marcos web, particularmente los Java, sí!), ¡Las marcas de tiempo serán las mismas dentro de una transacción! Una demostración:
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)
¿Nos vemos? Dos selecciones, exactamente el mismo resultado. No escribo tan rápido. ;-)
-
Si desea identificar fácilmente, evitando el uso de las secuencias, genere un valor hash a partir de los identificadores reales de los registros. Por ejemplo, si su base de datos tiene humanos, y sabe que su fecha de nacimiento, el apellido de soltera de la madre y el nombre real los identifica de manera única, entonces use un
md5(mother_name || '-' || given_name || '-' birthday);
como id. Además de eso, puede usar una CreationDate
columna, después de lo que indexa la tabla, pero no es una clave (que es la identificación).
Ps En general, es una muy buena práctica hacer que su DB sea tan determinista, como sea posible. Es decir, la misma operación debería crear exactamente el mismo cambio en la base de datos . Cualquier ID basado en la marca de tiempo falla esta importante característica. ¿Qué pasa si quieres depurar o simular algo? Vuelve a reproducir una operación y se creará el mismo objeto con una identificación diferente ... realmente no es difícil de seguir y ahorra muchas horas de trabajo.
Ps2 Cualquiera que verifique su código en el futuro, no tendrá la mejor opinión al ver los identificadores generados por la marca de tiempo, por los motivos anteriores.
INSERT
de varias filas, todas obtienen lo mismo current_timestamp
. Y luego tienes disparadores ...
No realmente porque es posible que CURRENT_TIMESTAMP proporcione dos valores idénticos para dos INSERTs posteriores (o un solo INSERT con varias filas).
Utilice un UUID basado en el tiempo en su lugar: uuid_generate_v1mc () .
Estrictamente hablando: No. Porque CURRENT_TIMESTAMP
es una función y solo una o más columnas de la tabla pueden formar una PRIMARY KEY
restricción.
Si quiere crear una PRIMARY KEY
restricción en una columna con el valor predeterminado CURRENT_TIMESTAMP
, la respuesta es: Sí, puede hacerlo . Nada le impide hacerlo, como nada le impide disparar manzanas de la cabeza de su hijo. La pregunta aún no tendría sentido mientras no definas el propósito de la misma. ¿Qué tipo de datos deben contener la columna y la tabla? ¿Qué reglas estás tratando de implementar?
Por lo general, la idea está destinada a errores de clave duplicados, ya que CURRENT_TIMESTAMP
es una STABLE
función que devuelve el mismo valor para la misma transacción (la hora de inicio de la transacción). Múltiples INSERTs en la misma transacción están obligados a colisionar, como otras respuestas ya ilustradas. El manual:
Dado que estas funciones devuelven la hora de inicio de la transacción actual, sus valores no cambian durante la transacción. Esto se considera una característica: la intención es permitir que una sola transacción tenga una noción coherente del tiempo "actual", de modo que múltiples modificaciones dentro de la misma transacción tengan la misma marca de tiempo.
Las marcas de tiempo de Postgres se implementan como enteros de 8 bytes que representan hasta 6 dígitos fraccionarios (resolución de microsegundos).
Si está creando una tabla que se supone que no debe contener más de una fila por microsegundo y esa condición no va a cambiar (algo llamado sensor_reading_per_microsecond
), entonces podría tener sentido. Se supone que las filas duplicadas generan un error de violación de clave duplicada. Sin embargo, esa es una excepción exótica. Y el tipo de datos timestamptz
(no timestamp
) probablemente sería preferible. Ver:
Todavía preferiría usar una clave primaria serial sustituta en su lugar. Y agregue una UNIQUE
restricción en la columna de marca de tiempo. Menos complicaciones posibles, sin depender de los detalles de implementación del RDBMS.
sensor_reading_per_microsecond
puede colisionar si no puede garantizar absolutamente que el tiempo de cada lectura esté perfectamente sincronizado con respecto al anterior; una desviación de menos de microsegundos (que a menudo no es imposible) rompe el esquema. En general, todavía evitaría esto por completo. (¡Ojo, como has indicado, en tal caso, la colisión resultante puede ser deseable!)