Insertar DATETIME y TIMESTAMP
MySQL tiene dos tipos para almacenar fecha y hora: DATETIME y TIMESTAMP. Ambos almacenan fechas con componente horaria, pero se comportan de forma diferente respecto a las zonas horarias y los valores por defecto. Entender sus diferencias es fundamental para manejar correctamente los datos temporales.
DATETIME vs TIMESTAMP
DATETIME almacena la fecha y hora tal cual la proporcionas, sin conversión de zona horaria. Rango: 1000-01-01 00:00:00 a 9999-12-31 23:59:59.
TIMESTAMP convierte internamente la hora a UTC al guardarla y la convierte de vuelta a la zona horaria de la sesión al leerla. Rango: 1970-01-01 00:00:01 a 2038-01-19 03:14:07 (limitado por el timestamp de Unix de 32 bits).
En nuestra tabla pedidos, la columna fecha_pedido es de tipo DATETIME. Las columnas creado_en y actualizado_en de la tabla productos son de tipo TIMESTAMP.
Insertar con formato estándar
El formato estándar es YYYY-MM-DD HH:MM:SS:
INSERT INTO pedidos (cliente_id, empleado_id, fecha_pedido, estado, total)
VALUES (1, 4, '2025-12-25 09:30:00', 'pendiente', 299.99);La fecha 2025-12-25 09:30:00 representa el 25 de diciembre de 2025 a las 9:30 de la mañana. Los segundos pueden omitirse y MySQL los pondrá a 00.
NOW() y CURRENT_TIMESTAMP
La función NOW() devuelve la fecha y hora actuales del servidor. Es la forma más habitual de insertar el momento actual:
INSERT INTO pedidos (cliente_id, empleado_id, fecha_pedido, estado, total)
VALUES (2, 5, NOW(), 'pendiente', 149.99);NOW() y CURRENT_TIMESTAMP son sinónimos y devuelven el mismo valor. En la definición de tablas, CURRENT_TIMESTAMP es la forma preferida para valores por defecto:
CREATE TABLE log_acciones (
id INT AUTO_INCREMENT PRIMARY KEY,
accion VARCHAR(200),
fecha_hora DATETIME DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO log_acciones (accion) VALUES ('Usuario inició sesión');Al no proporcionar fecha_hora, MySQL usa automáticamente CURRENT_TIMESTAMP.
Precisión de fracciones de segundo
MySQL 5.6.4+ soporta fracciones de segundo con precisión de hasta 6 dígitos (microsegundos):
CREATE TABLE log_preciso (
id INT AUTO_INCREMENT PRIMARY KEY,
evento VARCHAR(200),
marca_tiempo DATETIME(3) -- 3 dígitos de precisión (milisegundos)
);
INSERT INTO log_preciso (evento, marca_tiempo)
VALUES ('Click en botón', '2025-12-25 09:30:15.123');
INSERT INTO log_preciso (evento, marca_tiempo)
VALUES ('Página cargada', NOW(3));DATETIME(3) almacena hasta 3 decimales de segundo. NOW(3) devuelve la hora actual con 3 decimales de precisión. Esto es útil para medir tiempos de respuesta o registrar eventos con precisión de milisegundos.
TIMESTAMP y zonas horarias
La diferencia clave de TIMESTAMP es la conversión automática de zona horaria. Observa cómo cambia el valor según la zona horaria de la sesión:
CREATE TABLE test_timestamp (
id INT AUTO_INCREMENT PRIMARY KEY,
valor TIMESTAMP
);
SET SESSION time_zone = '+01:00'; -- Madrid (CET)
INSERT INTO test_timestamp (valor) VALUES ('2025-12-25 12:00:00');
SET SESSION time_zone = '+00:00'; -- UTC
SELECT * FROM test_timestamp;| id | valor |
|---|---|
| 1 | 2025-12-25 11:00:00 |
Insertamos las 12:00 en horario de Madrid (CET, UTC+1). Al consultarlo en UTC, se muestra como las 11:00. MySQL convirtió automáticamente la hora. DATETIME no haría esta conversión: siempre mostraría 12:00:00 sin importar la zona horaria.
Actualización automática con ON UPDATE
TIMESTAMP tiene una característica exclusiva: puede actualizarse automáticamente cuando se modifica la fila:
CREATE TABLE ejemplo_auto (
id INT AUTO_INCREMENT PRIMARY KEY,
dato VARCHAR(100),
creado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
actualizado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
INSERT INTO ejemplo_auto (dato) VALUES ('valor inicial');Nuestra tabla productos usa exactamente este patrón. Al insertar, ambas columnas reciben la fecha actual. Cuando hagas un UPDATE sobre la fila, actualizado_en se actualizará automáticamente sin que tengas que especificarlo.
Insertar con aritmética de fechas
Puedes calcular fechas y horas al insertar:
-- Pedido con fecha de mañana a las 10:00
INSERT INTO pedidos (cliente_id, empleado_id, fecha_pedido, estado, total)
VALUES (1, 4, CURDATE() + INTERVAL 1 DAY + INTERVAL 10 HOUR, 'pendiente', 50.00);
-- Fecha y hora hace 2 horas
INSERT INTO pedidos (cliente_id, empleado_id, fecha_pedido, estado, total)
VALUES (3, 6, NOW() - INTERVAL 2 HOUR, 'procesando', 75.00);Puedes encadenar múltiples INTERVAL y usar unidades como SECOND, MINUTE, HOUR, DAY, MONTH, YEAR.
STR_TO_DATE con hora
Para convertir cadenas con formatos no estándar que incluyen hora:
INSERT INTO pedidos (cliente_id, empleado_id, fecha_pedido, estado, total)
VALUES (
1, 4,
STR_TO_DATE('25-Dic-2025 14:30', '%d-%b-%Y %H:%i'),
'pendiente',
100.00
);Los especificadores horarios más usados son:
%H Hora en formato 24h (00-23)
%h Hora en formato 12h (01-12)
%i Minutos (00-59)
%s Segundos (00-59)
%p AM o PM
Cuándo usar DATETIME vs TIMESTAMP
Usa DATETIME cuando la fecha y hora deben ser absolutas: fechas de nacimiento, eventos programados, fechas de caducidad. El valor siempre será el mismo independientemente de quién lo consulte.
Usa TIMESTAMP cuando necesitas registrar "cuándo pasó algo": fecha de creación de un registro, última modificación, último acceso. La conversión automática de zona horaria es una ventaja cuando tienes usuarios en diferentes husos horarios.
Limpiar
DROP TABLE IF EXISTS log_acciones, log_preciso, test_timestamp, ejemplo_auto;En el siguiente artículo veremos la sentencia UPDATE para modificar datos existentes en las tablas.
Escrito por Eduardo Lázaro
