2008-11-06 20 views
108

Tengo el siguiente esquema de tabla;Tener una columna de marca de tiempo creada y última actualizada en MySQL 4.0

CREATE TABLE `db1`.`sms_queue` (
    `Id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, 
    `Message` VARCHAR(160) NOT NULL DEFAULT 'Unknown Message Error', 
    `CurrentState` VARCHAR(10) NOT NULL DEFAULT 'None', 
    `Phone` VARCHAR(14) DEFAULT NULL, 
    `Created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `LastUpdated` TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, 
    `TriesLeft` tinyint NOT NULL DEFAULT 3, 
    PRIMARY KEY (`Id`) 
) 
ENGINE = InnoDB; 

falla con el siguiente error:

ERROR 1293 (HY000): Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause. 

Mi pregunta es, ¿puedo tener ambos de estos campos? o tengo que configurar manualmente un campo LastUpdated durante cada transacción?

+0

Hola, @Xenph Yan, ¿te importaría cambiar la respuesta "Aceptada" de la incorrecta actual a la correcta? Este aceptado, respuesta equivocada me hizo perder unos 15 minutos tratando de averiguar lo que estaba pasando ... –

+1

@BrunoReis hecho esto, gracias por la recogida. –

Respuesta

95

From the MySQL 5.5 documentation:

One TIMESTAMP column in a table can have the current timestamp as the default value for initializing the column, as the auto-update value, or both. It is not possible to have the current timestamp be the default value for one column and the auto-update value for another column.

Changes in MySQL 5.6.5:

Previously, at most one TIMESTAMP column per table could be automatically initialized or updated to the current date and time. This restriction has been lifted. Any TIMESTAMP column definition can have any combination of DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP clauses. In addition, these clauses now can be used with DATETIME column definitions. For more information, see Automatic Initialization and Updating for TIMESTAMP and DATETIME.

+4

+1 Gracias por el pesaje oficial de la documentación. –

+0

Eso ha cambiado (al menos en MySQL 5.0). Consulte la documentación: http://dev.mysql.com/doc/refman/5.0/en/timestamp.html – SimonSimCity

+0

Lucha contra @SimonSimCity: Los documentos de 5.0 dicen exactamente lo mismo que el anterior. – davemyron

26

Puede tener ambas, simplemente despegue el indicador "CURRENT_TIMESTAMP" en el campo creado. Siempre que cree un nuevo registro en la tabla, simplemente use "AHORA()" para un valor.

Or.

Por el contrario, elimine el indicador 'ACTUALIZAR ACTUALIZADO CURRENT_TIMESTAMP' y envíe el AHORA() para ese campo. De esa manera, en realidad tiene más sentido.

+2

¿Es esta la única manera? No puedo hacer que la base de datos se ocupe de todos esos detalles? –

+2

De acuerdo con el manual de MySQL, CURRENT_TIMESTAMP es un sinónimo de NOW(), así que no creo que esto va a funcionar. – tvanfosson

+0

Estoy seguro de que puedes, es solo que CURRENT_TIMESTAMP es una bandera reservada para un solo campo. De cualquier manera, si tuviera esa bandera allí, independientemente del valor que tenga para ese campo cuando agregue un registro, siempre será la marca de tiempo actual, de ahí el nombre. –

80

There is a trick que tienen ambas marcas de tiempo, pero con un poco de limitación.

Puede usar solo una de las definiciones en una tabla. Crear dos columnas de fecha y hora, así:

create table test_table( 
    id integer not null auto_increment primary key, 
    stamp_created timestamp default '0000-00-00 00:00:00', 
    stamp_updated timestamp default now() on update now() 
); 

Tenga en cuenta que es necesario introducir null en ambas columnas durante insert:

mysql> insert into test_table(stamp_created, stamp_updated) values(null, null); 
Query OK, 1 row affected (0.06 sec) 

mysql> select * from test_table; 
+----+---------------------+---------------------+ 
| id | stamp_created  | stamp_updated  | 
+----+---------------------+---------------------+ 
| 2 | 2009-04-30 09:44:35 | 2009-04-30 09:44:35 | 
+----+---------------------+---------------------+ 
2 rows in set (0.00 sec) 

mysql> update test_table set id = 3 where id = 2; 
Query OK, 1 row affected (0.05 sec) Rows matched: 1 Changed: 1 Warnings: 0 

mysql> select * from test_table; 
+----+---------------------+---------------------+ 
| id | stamp_created  | stamp_updated  | 
+----+---------------------+---------------------+ 
| 3 | 2009-04-30 09:44:35 | 2009-04-30 09:46:59 | 
+----+---------------------+---------------------+ 
2 rows in set (0.00 sec) 
+0

El enlace está ahora muerto. –

+0

Aquí hay un enlace de la documentación de MySQL que describe esa función: http://dev.mysql.com/doc/refman/5.0/en/timestamp.html – SimonSimCity

+0

No se puede hacer que esto funcione con 5.5.22-0ubuntu1 –

21

Si decide tener MySQL manejar la actualización de las marcas de tiempo, que puede configurar un activador para actualizar el campo en la inserción.

CREATE TRIGGER <trigger_name> BEFORE INSERT ON <table_name> FOR EACH ROW SET NEW.<timestamp_field> = CURRENT_TIMESTAMP; 

MySQL Referencia: http://dev.mysql.com/doc/refman/5.0/en/triggers.html

+0

Bueno, esto era lo que estaba buscando. No quiero tener que depender de personas agregadas AHORA() en la consulta. – Bot

+0

En realidad, sería mejor hacerlo después de la inserción, y establecer NUEVO. = new. de esta manera ambos campos son constantes – KacieHouser

+0

@KacieHouser No se permite la actualización de NUEVA fila después disparador – Thomas

20

Esto es ¿cómo se puede tener automáticas & CreateDate flexibles/campos LastModified utilizando los factores causales:

Primero los definen como esto:

CREATE TABLE `entity` (
    `entityid` int(11) NOT NULL AUTO_INCREMENT, 
    `createDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `lastModified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `name` varchar(255) DEFAULT NULL, 
    `comment` text, 
    PRIMARY KEY (`entityid`), 
) 

Publique estos factores desencadenantes:

DELIMITER ;; 
CREATE trigger entityinsert BEFORE INSERT ON entity FOR EACH ROW BEGIN SET NEW.createDate=IF(ISNULL(NEW.createDate) OR NEW.createDate='0000-00-00 00:00:00', CURRENT_TIMESTAMP, IF(NEW.createDate<CURRENT_TIMESTAMP, NEW.createDate, CURRENT_TIMESTAMP));SET NEW.lastModified=NEW.createDate; END;; 
DELIMITER ; 
CREATE trigger entityupdate BEFORE UPDATE ON entity FOR EACH ROW SET NEW.lastModified=IF(NEW.lastModified<OLD.lastModified, OLD.lastModified, CURRENT_TIMESTAMP); 
  • Si inserta sin especificar CreateDate o lastModified, que será igual y establecer la fecha y hora actual.
  • Si actualiza sin especificar createDate o lastModified, lastModified se establecerá en la marca de tiempo actual.

Pero aquí está la parte buena:

  • Si inserta, se puede especificar un CreateDate más antigua que la fecha y hora actual, permitiendo que las importaciones procedentes de otros tiempos para trabajar bien (lastModified será igual para crear Fecha).
  • Si actualizar, se puede especificar un LastModified mayor que el valor anterior ('0000-00-00 00:00:00' funciona bien), lo que permite actualizar una entrada, si está haciendo cambios cosméticos (fijación de un error tipográfico en un comentario) y que desea mantener el viejo fecha lastModified. Esto no modificará la última fecha modificada.
+1

Esta es una gran respuesta/solución. ¡Mereces más crédito! –

3

Este problema parecía haber sido resuelto en MySQL 5.6. Lo he notado hasta MySQL 5.5; aquí es un código de ejemplo:

DROP TABLE IF EXISTS `provider_org_group` ; 
CREATE TABLE IF NOT EXISTS `provider_org_group` (
    `id` INT NOT NULL, 
    `name` VARCHAR(100) NOT NULL, 
    `type` VARCHAR(100) NULL, 
    `inserted` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `insert_src_ver_id` INT NULL, 
    `updated` TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP, 
    `update_src_ver_id` INT NULL, 
    `version` INT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE INDEX `id_UNIQUE` (`id` ASC), 
    UNIQUE INDEX `name_UNIQUE` (`name` ASC)) 
ENGINE = InnoDB; 

La ejecución de este en MySQL 5.5 da:

ERROR 1293 (HY000): Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause 

La ejecución de este en MySQL 5,6

0 row(s) affected 0.093 sec 
+0

esto es desde MySQL 5.6 la respuesta correcta. – q0re

12

En MySQL 5.6 es fácil peasy ... Pruébalo:

create table tweet ( 
    id integer not null auto_increment primary key, 
    stamp_created timestamp default now(), 
    stamp_updated timestamp default now() on update now(), 
    message varchar(163) 
) 
+0

Gracias. Esto funciono muy bien para mi. – Andi

+0

Probablemente una gran solución Lo que estoy buscando crea y actualiza el problema del tiempo sin desencadenar – matinict

Cuestiones relacionadas