¿Cómo establece un valor predeterminado para una columna MySQL Datetime?


898

¿Cómo establece un valor predeterminado para una columna MySQL Datetime?

En SQL Server es getdate(). ¿Cuál es el equivalente para MySQL? Estoy usando MySQL 5.x si eso es un factor.


44
Uso CURRENT_TIMESTAMP en mi tabla mysql (no en la consulta), tal vez esto también pueda ser útil.
Ruben

15
Esta característica ahora se ha agregado a MySQL 5.6.5. Espero que esto ayude a alguien. optimize-this.blogspot.co.uk/2012/04/...
GhostInTheSecureShell

@GhostInTheSecureShell tiene la misión de instalarlo, al menos en Debian, pero definitivamente es una característica increíble. ¡Creo que eventualmente todas estas "dos CURRENT_TIMESTAMP" serán aliviadas!
Marc DiMillo

ahora es función () o puede hacerlo con la configuración predeterminada en el nivel de columna.
Anshul Sharma

Respuestas:


862

EDICIÓN IMPORTANTE: ahora es posible lograr esto con los campos DATETIME desde MySQL 5.6.5 , eche un vistazo a la otra publicación a continuación ...

Las versiones anteriores no pueden hacer eso con DATETIME ...

Pero puedes hacerlo con TIMESTAMP:

mysql> create table test (str varchar(32), ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.00 sec)

mysql> desc test;
+-------+-------------+------+-----+-------------------+-------+
| Field | Type        | Null | Key | Default           | Extra |
+-------+-------------+------+-----+-------------------+-------+
| str   | varchar(32) | YES  |     | NULL              |       | 
| ts    | timestamp   | NO   |     | CURRENT_TIMESTAMP |       | 
+-------+-------------+------+-----+-------------------+-------+
2 rows in set (0.00 sec)

mysql> insert into test (str) values ("demo");
Query OK, 1 row affected (0.00 sec)

mysql> select * from test;
+------+---------------------+
| str  | ts                  |
+------+---------------------+
| demo | 2008-10-03 22:59:52 | 
+------+---------------------+
1 row in set (0.00 sec)

mysql>

** CAVEAT: SI define una columna con CURRENT_TIMESTAMP ON por defecto, SIEMPRE necesitará especificar un valor para esta columna o el valor se restablecerá automáticamente a "now ()" en la actualización. Esto significa que si no desea que el valor cambie, su instrucción UPDATE debe contener "[su nombre de columna] = [su nombre de columna]" (o algún otro valor) o el valor se convertirá en "ahora ()". Extraño, pero cierto. Espero que esto ayude. Estoy usando 5.5.56-MariaDB **


400
Es importante tener en cuenta que la fecha y hora tiene un rango de 1000-9999, pero el rango de la marca de tiempo es solo 1970-2038 . Esto puede ser un problema si su sistema tiene que almacenar fechas de nacimiento, o si tiene que manejar algo como el plan de pago para una hipoteca a 30 años. dev.mysql.com/doc/refman/5.0/en/datetime.html
Kip

13
Tenga cuidado también con la marca de tiempo, ya que se actualiza automáticamente mágicamente ... vea la próxima respuesta stackoverflow.com/a/1483959/233906
Cerber

66
Que es posible a partir de la versión 5.6.5, véase la respuesta de Gustav continuación (Me doy cuenta de que su respuesta fue publicada cuando MySQL todavía era 5.0!)
e2-e4

44
@Kip, Hola, ¿es posible tener un valor predeterminado para una DATEcolumna? (no una datetimecolumna)
Sajib Acharya

ti no parece posible para las columnas DATE: debe usar el tipo de datos DATETIME
Fabio Napodano

599

En la versión 5.6.5, es posible establecer un valor predeterminado en una columna de fecha y hora, e incluso crear una columna que se actualizará cuando se actualice la fila. La definición del tipo:

CREATE TABLE foo (
    `creation_time`     DATETIME DEFAULT CURRENT_TIMESTAMP,
    `modification_time` DATETIME ON UPDATE CURRENT_TIMESTAMP
)

Referencia: http://optimize-this.blogspot.com/2012/04/datetime-default-now-finally-available.html


3
Valor predeterminado no válido para 'menu_creation_time'
Fernando Trindade

2
@FernandoTrindade Necesita MySQL versión 5.6.5 o posterior. Puedes verlo trabajando aquí: sqlfiddle.com/#!9/dd2be
Gustav Bertram

1
@GustavBertram, estoy usando la versión 5.6.22, pero aún recibí el siguiente error: CREATE TABLE tbl (InsertDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, UpdateDate TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP (6)); Código de error: 1294. Cláusula ON UPDATE no válida para la columna 'UpdateDate'
Manish Sapkal

@ManishSapkal Estás utilizando un TIMESTAMP, no un DATETIME. Además, no lo hagas NULL.
Gustav Bertram

1
Creo que la sintaxis "ACTUALIZACIÓN" está mal. De acuerdo con dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html debería serdt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Dan Bough

148

MySQL ( antes de la versión 5.6.5 ) no permite que se usen funciones para los valores predeterminados de DateTime. TIMESTAMP no es adecuado debido a su comportamiento extraño y no se recomienda su uso como datos de entrada. (Consulte Valores predeterminados del tipo de datos MySQL ).

Dicho esto, puedes lograr esto creando un Trigger .

Tengo una tabla con un campo DateCreated de tipo DateTime. Creé un disparador en esa tabla "Antes de insertar" y " SET NEW.DateCreated=NOW()" y funciona muy bien.

Espero que esto ayude a alguien.


21
CREATE TRIGGER trigger_foo_SetCreatedAt ANTES DE INSERTAR EN foo PARA CADA FILA SET NEW.created_at = UTC_TIMESTAMP ();
kgriffs

55
Probablemente sea mejor usar una marca de tiempo que un disparador para la cordura futura (mantenimiento). Este es un caso de uso demasiado trivial para un desencadenante, aunque es una solución.
getWeberForStackExchange

8
Probablemente solo desee establecer el valor predeterminadoIF NEW.created_at IS NOT NULL
Petr Peller, el

132

Para mí, el enfoque de disparo ha funcionado mejor, pero encontré un inconveniente con el enfoque. Considere el disparador básico para establecer un campo de fecha a la hora actual en la inserción:

CREATE TRIGGER myTable_OnInsert BEFORE INSERT ON `tblMyTable`
    FOR EACH ROW SET NEW.dateAdded = NOW();

Esto suele ser genial, pero digamos que desea establecer el campo manualmente a través de la instrucción INSERT, así:

INSERT INTO tblMyTable(name, dateAdded) VALUES('Alice', '2010-01-03 04:30:43');

Lo que sucede es que el activador sobrescribe inmediatamente el valor proporcionado para el campo, por lo que la única forma de establecer una hora no actual es una declaración de ACTUALIZACIÓN de seguimiento: ¡qué asco! Para anular este comportamiento cuando se proporciona un valor, pruebe este disparador ligeramente modificado con el operador IFNULL:

CREATE TRIGGER myTable_OnInsert BEFORE INSERT ON `tblMyTable`
    FOR EACH ROW SET NEW.dateAdded = IFNULL(NEW.dateAdded, NOW());

Esto brinda lo mejor de ambos mundos: puede proporcionar un valor para su columna de fecha y tomará, y de lo contrario, se establecerá de manera predeterminada a la hora actual. Todavía es un ghetto en relación con algo limpio como DEFAULT GETDATE () en la definición de la tabla, ¡pero nos estamos acercando!


55
+1 para reconocer la advertencia con la sobrescritura de valores explícitos de usuario en la inserción.
Kip

2
Personalmente, creo que este es el mejor camino a seguir. TIMESTAMP tiene un comportamiento extraño y nunca escribiría código que tenga una limitación de 2038 años.
Eric

No importa, lo descubrí. Olvidé configurar el campo para permitir NULL. No hay advertencias más.
Kaji

¡Los disparadores son malvados! Solo úselas cuando no haya otra forma de hacer algo. Es mejor actualizar a 5.6.x id que puede usar que un disparador.
ksymeon

44
En MySQL 5.5, IFNULL no funciona en DATETIME; usando el disparador anterior, dateAddedse mostrarán todos los '0000-00-00 00:00:00'. Usar esto hace el truco: `PARA CADA FILA SI ES NUEVO. DateAdded = 0 LUEGO ESTABLECE NEW.dateAdded = NOW (); END IF; `
Kenney

28

Pude resolver esto usando esta declaración alter en mi tabla que tenía dos campos de fecha y hora.

ALTER TABLE `test_table`
  CHANGE COLUMN `created_dt` `created_dt` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
  CHANGE COLUMN `updated_dt` `updated_dt` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

Esto funciona como es de esperar que funcione la función now (). Insertar nulos o ignorar los campos created_dt y updated_dt da como resultado un valor de marca de tiempo perfecto en ambos campos. Cualquier actualización de la fila cambia el updated_dt. Si inserta registros a través del navegador de consultas MySQL, necesita un paso más, un activador para manejar el created_dt con una nueva marca de tiempo.

CREATE TRIGGER trig_test_table_insert BEFORE INSERT ON `test_table`
    FOR EACH ROW SET NEW.created_dt = NOW();

El desencadenador puede ser lo que quieras Simplemente me gusta la convención de nomenclatura [trig] _ [my_table_name] _ [insert]


Quise decir, si inserta registros a través del navegador de consultas MySQL manualmente a través de la cuadrícula sin una instrucción insert (), se necesita el desencadenante. Si siempre usa una instrucción de inserción, el desencadenante es completamente innecesario.

Whoops! Quise decir que El desencadenante (nombre) puede ser lo que quieras porque el nombre del desencadenante no afecta en absoluto la funcionalidad. La mayoría de la gente va a saber que, pero algunas personas nuevas a MySQL puede no saber ...

Ay, perdón por la falta de saltos de línea. Usa los punto y coma para marcar el final de cada línea.

24

Puedes usar disparadores para hacer este tipo de cosas.

CREATE TABLE `MyTable` (
`MyTable_ID`  int UNSIGNED NOT NULL AUTO_INCREMENT ,
`MyData`  varchar(10) NOT NULL ,
`CreationDate`  datetime NULL ,
`UpdateDate`  datetime NULL ,
PRIMARY KEY (`MyTable_ID`)
)
;

CREATE TRIGGER `MyTable_INSERT` BEFORE INSERT ON `MyTable`
FOR EACH ROW BEGIN
        -- Set the creation date
    SET new.CreationDate = now();

        -- Set the udpate date
    Set new.UpdateDate = now();
END;

CREATE TRIGGER `MyTable_UPDATE` BEFORE UPDATE ON `MyTable`
FOR EACH ROW BEGIN
        -- Set the udpate date
    Set new.UpdateDate = now();
END;

18

Para todos aquellos que se desanimaron tratando de establecer un valor DATETIME predeterminado en MySQL , sé exactamente cómo se siente / sintió. Entonces aquí está:

ALTER TABLE  `table_name` CHANGE `column_name` DATETIME NOT NULL DEFAULT 0

Observe cuidadosamente que no he agregado comillas simples / comillas dobles alrededor del 0

Estoy literalmente saltando después de resolver este: D


8
No inserta ni la hora actual. Insertará '0000-00-00 00:00:00'.
Pit Digger

8
No dije que establezca la hora actual. Muchas personas estaban / están tratando de establecer un valor cero predeterminado, pero simplemente no funciona. Necesitamos eliminar las comillas. Como este hallazgo causó mucho tiempo y frustración, pensé en compartirlo con la comunidad. Las personas como usted son responsables de que los usuarios pierdan interés en compartir información útil con otras personas. En serio, no veo ninguna razón para obtener un -1. Lo que sea.
Augiwan

3
Lo mismo podría lograrse con DATETIME NOT NULL.
Brendan Byrd

Hay un `carácter más dentro del comando sql de ejemplo, que no puedo editar, ya que es solo una edición de carácter.
Quapka

su código no funcionó para mí, esto es lo que funcionóALTER TABLE zones MODIFY created datetime NOT NULL DEFAULT 0;
Smith


14

Si ya ha creado la tabla, puede usar

Para cambiar el valor predeterminado a la fecha y hora actual

ALTER TABLE <TABLE_NAME> 
CHANGE COLUMN <COLUMN_NAME> <COLUMN_NAME> DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;

Para cambiar el valor predeterminado a '2015-05-11 13:01:01'

ALTER TABLE <TABLE_NAME> 
CHANGE COLUMN <COLUMN_NAME> <COLUMN_NAME> DATETIME NOT NULL DEFAULT '2015-05-11 13:01:01';


9

Estoy ejecutando MySql Server 5.7.11 y esta oración:

ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '0000-00-00 00:00:00'

es no trabajar. Pero lo siguiente:

ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '1000-01-01 00:00:00'

solo funciona .

Como nota al margen , se menciona en los documentos de mysql :

El tipo DATE se usa para valores con una parte de fecha pero sin parte de tiempo. MySQL recupera y muestra los valores de FECHA en formato 'AAAA-MM-DD'. El rango admitido es '1000-01-01' a '9999-12-31'.

incluso si también dicen:

Los valores DATE, DATETIME o TIMESTAMP no válidos se convierten al valor "cero" del tipo apropiado ('0000-00-00' o '0000-00-00 00:00:00').


8

Puede usar now () para establecer el valor de una columna de fecha y hora, pero tenga en cuenta que no puede usarlo como valor predeterminado.


44
cierto. Acabo de intentar usar ahora y recibí un error "Código de error: 1067. Valor predeterminado no válido" Entonces, ¿cuál es la respuesta? ;-)
Brian Boatright

Esta es la mejor solución para comprometer las versiones de MySQL 5.5 y 5.6. Para la versión 5.5, predetermine el valor NOW()y utilícelo más tarde para la inserción. Para la versión 5.6, simplemente establezca NOW()el valor predeterminado.
Abel Callejo

8

Para todos los que usan la columna TIMESTAMP como solución, quiero secundar la siguiente limitación del manual:

http://dev.mysql.com/doc/refman/5.0/en/datetime.html

"El tipo de datos TIMESTAMP tiene un rango de '1970-01-01 00:00:01' UTC a ' 2038-01-19 03:14:07 ' UTC. Tiene propiedades variables, dependiendo de la versión de MySQL y el SQL modo en el que se ejecuta el servidor. Estas propiedades se describen más adelante en esta sección ".

Obviamente, esto romperá su software en aproximadamente 28 años.

Creo que la única solución en el lado de la base de datos es usar disparadores como se menciona en otras respuestas.


2
¿Qué pasa si MySQL se actualizó dentro de 20 años y se eliminó esa limitación? No estoy seguro de si eso es posible, pero solo un pensamiento.
NessDan

7

Al definir disparadores de líneas múltiples, uno tiene que cambiar el delimitador, ya que el compilador MySQL tomará el punto y coma como final del disparador y generará un error. p.ej

DELIMITER //
CREATE TRIGGER `MyTable_UPDATE` BEFORE UPDATE ON `MyTable`
FOR EACH ROW BEGIN
        -- Set the udpate date
    Set new.UpdateDate = now();
END//
DELIMITER ;

5

Aquí se explica cómo hacerlo en MySQL 5.1:

ALTER TABLE `table_name` CHANGE `column_name` `column_name` 
TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;

No tengo idea de por qué debe ingresar el nombre de la columna dos veces.


55
CAMBIO también es para renombrar el campo. El nombre de la primera columna es el "antiguo", el nombre de la segunda columna es el "nuevo". Parece redundante si no está cambiando el nombre del campo. Si es demasiado desagradable estéticamente, intente MODIFICAR.
John Gordon

5

Si bien no puede hacer esto con DATETIMEla definición predeterminada, simplemente puede incorporar una declaración de selección en su declaración de inserción de esta manera:

INSERT INTO Yourtable (Field1, YourDateField) VALUES('val1', (select now()))

Tenga en cuenta la falta de comillas alrededor de la mesa.

Para MySQL 5.5


3

Si está intentando establecer el valor predeterminado como AHORA (), no creo que MySQL lo admita. En MySQL, no puede usar una función o una expresión como valor predeterminado para ningún tipo de columna, excepto para la columna de tipo de datos TIMESTAMP, para la cual puede especificar CURRENT_TIMESTAMP como predeterminado.


3

Creo que es simple en mysql ya que mysql es la función incorporada llamada now () que proporciona la hora actual (hora de esa inserción).

Entonces su consulta debería verse de manera similar

CREATE TABLE defaultforTime(
    `creation_time`     DATETIME DEFAULT CURRENT_TIMESTAMP,
    `modification_time` DATETIME default now()
);

Gracias.


2
CREATE TABLE `testtable` (
    `id` INT(10) NULL DEFAULT NULL,
    `colname` DATETIME NULL DEFAULT '1999-12-12 12:12:12'
)

En la consulta anterior para crear 'testtable', usé '1999-12-12 12:12:12' como valor predeterminado para la columna DATETIME colname


1

Usa el siguiente código

DELIMITER $$

    CREATE TRIGGER bu_table1_each BEFORE UPDATE ON table1 FOR EACH ROW
    BEGIN
      SET new.datefield = NOW();
    END $$

    DELIMITER ;

0

Si está intentando establecer el valor predeterminado como AHORA (), MySQL admite que debe cambiar el tipo de esa columna TIMESTAMP en lugar de DATETIME. TIMESTAMP tiene la fecha y hora actuales como predeterminadas ... creo que resolverá su problema ...


0

Tomemos, por ejemplo, si tuviera una tabla llamada 'sitio' con una columna created_at y update_at que fueran DATETIME y necesiten el valor predeterminado de ahora, podría ejecutar el siguiente sql para lograr esto.

ALTER TABLE `site` CHANGE` created_at` `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;

ALTER TABLE `site` CHANGE` created_at` `created_at` DATETIME NULL DEFAULT NULL;

ALTER TABLE `site` CHANGE` updated_at` `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;

ALTER TABLE `site` CHANGE` updated_at` `updated_at` DATETIME NULL DEFAULT NULL;

La secuencia de declaraciones es importante porque una tabla no puede tener dos columnas de tipo TIMESTAMP con valores predeterminados de CUREENT TIMESTAMP


0

Este es mi ejemplo de activación:

/************ ROLE ************/
drop table if exists `role`;
create table `role` (
    `id_role` bigint(20) unsigned not null auto_increment,
    `date_created` datetime,
    `date_deleted` datetime,
    `name` varchar(35) not null,
    `description` text,
    primary key (`id_role`)
) comment='';

drop trigger if exists `role_date_created`;
create trigger `role_date_created` before insert
    on `role`
    for each row 
    set new.`date_created` = now();


0

Trabajando bien con MySQL 8.x

CREATE TABLE `users` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `dateCreated` datetime DEFAULT CURRENT_TIMESTAMP,
      `dateUpdated` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`),
      UNIQUE KEY `mobile_UNIQUE` (`mobile`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-3

Puede resolver la marca de tiempo predeterminada. Primero considere qué juego de caracteres está utilizando, por ejemplo, si tomó utf8, este juego de caracteres admite todos los idiomas y si tomó late1 este juego de caracteres solo admite inglés. Luego, si está trabajando en algún proyecto, debe conocer la zona horaria del cliente y seleccionar la zona del cliente. Este paso es obligatorio.


2
Las columnas DateTime no pueden tener valores predeterminados. Está documentado 'característica'. No todos los desarrolladores tienen acceso para cambiar su codificación de caracteres. Y configurar el servidor en la zona horaria de sus clientes generalmente no es una posibilidad, especialmente cuando los clientes no son todos nativos de un área de zona horaria única.
rlb.usa
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.