2011-07-05 9 views
9

Me gustaría crear una tabla que tenga una columna para "creado" y otra para "actualizado". La columna "creada" se configurará en insertar y nunca cambiará. La columna "actualizada" cambiará cada vez que se actualice una fila. No quiero meterme con ninguna de estas columnas en las siguientes instrucciones INSERT o UPDATE. Entonces, ¿cómo debería ser mi declaración CREATE TABLE si empiezo con algo como esto?Dos columnas de indicación de fecha y hora MySQL en una tabla

CREATE TABLE IF NOT EXISTS `mydb`.`mytable` (
    `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    `updated` TIMESTAMP, 
    `created` TIMESTAMP, 
    `deleted` TINYINT DEFAULT 0, 
    `notes` TEXT DEFAULT '', 
    `description` VARCHAR(100) 
) TYPE=innodb; 

Parece que tengo problemas para crear una tabla con dos columnas TIMESTAMP. No me importa si las columnas son TIMESTAMP o DATETIME o lo que sea, solo quiero que sean rellenas por MySQL sin instrucciones explícitas de las instrucciones de inserción o actualización.

Me gustaría ser capaz de hacer inserciones de la siguiente manera:

INSERT INTO `mydb`.`mytable` (notes,description) VALUES ('some note','some description'); 

y actualizaciones como esta:

UPDATE `mydb`.`mytable` SET notes=CONCAT(notes,'some more notes') WHERE id=1; 

tanto sin tener que establecer explícitamente la columna "creado" o conjunto (o restablecer) la columna "actualizada" en la instrucción de inserción o actualización.

+0

Es necesario un desencadenador UPDATE ON para actualizar el " "columna actualizada" cada vez que ocurre una actualización. Yo respondería con un ejemplo completo, pero no sé cómo se hace en MySQL, ya que solo uso PostgreSQL en estos días. Pero estoy seguro de que el manual de MySQL le proporcionará la sintaxis completa. – Flimzy

+1

posible duplicado de [Una tabla Mysql con múltiples columnas TIMESTAMP] (http://stackoverflow.com/questions/4851672/one-mysql-table-with-multiple-timestamp-columns) –

Respuesta

7

intente éste para crear la tabla:

CREATE TABLE IF NOT EXISTS db.test_table 
(
Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
created DATETIME DEFAULT NULL, 
updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
deleted TINYINT DEFAULT 0, 
notes TEXT DEFAULT NULL, 
description VARCHAR(100) 
) 

Tenga en cuenta que

updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 

permitirá actualizar este campo autom aticamente

Y configurar éste para un disparador antes de insertar registros:

DELIMITER $$ 

CREATE 
    /*[DEFINER = { user | CURRENT_USER }]*/ 
    TRIGGER `db`.`on_before_insert` BEFORE INSERT 
    ON `db`.`test_table` 
    FOR EACH ROW BEGIN 
    SET new.created = NOW();  
    END$$ 

DELIMITER ; 

continuación, puede utilizar esta opción para insertar:

INSERT INTO db.test_table(description) VALUES ("Description") 

y actualizar su registro

UPDATE db.test_table SET description = "Description 2" where Id=1 

Y sus campos creados y actualizados se establecerán de forma adecuada.

+0

ganas por la respuesta más explícita a la pregunta que se hizo. La respuesta de @Dark Slipstream también tiene mucho que ofrecer. –

+0

Creo que la marca de tiempo debe usarse tanto para crear como para actualizar. Con la versión 5.5 de mysql, puede establecer la marca de tiempo creada como predeterminada en current_timestamp y puede configurar la marca de tiempo actualizada para que se actualice automáticamente en las actualizaciones Y establecer la fecha de inicio predeterminada. Y no es necesario disparar. –

0

Desafortunadamente, MySQL no le permite tener dos columnas TIMESTAMP en una misma tabla. Utilizaría ON UPDATE CURRENT_TIMESTAMP para la columna actualizada y el conjunto creado manualmente usando la función NOW().

+0

Como se señaló en mi pregunta, la configuración "creado "manualmente es lo que explícitamente quiero evitar. –

+0

¡Sinceramente espero estar equivocado y hay una mejor manera de hacerlo! :) –

+0

Andreas Jansson, a pesar de que no es compatible solo con definiciones de tabla, esto aún es muy fácil de lograr. Ver la respuesta de james_bond. –

2

Prueba esto:

CREATE TABLE IF NOT EXISTS mydb.mytable 
(
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    updated DATETIME, 
    created TIMESTAMP, 
    deleted TINYINT DEFAULT 0, 
    notes TEXT DEFAULT '', 
    description VARCHAR(100) 
) TYPE=innodb; 

Editar: Utilice un disparador.

CREATE TRIGGER mytable_update 
BEFORE UPDATE ON mydb.mytable 
    FOR EACH ROW SET NEW.updated = NOW(); 
+0

No creo que DATETIME pueda ser DEFAULT NOW() –

+0

Tiene razón ... buscando otra solución ... –

+0

Aparece el siguiente error con el código de arriba: –

1

Noticias de última hora: en MySQL, TIMESTAMP columnas siempre se actualizan con now() cada vez que cualquier otra columna en la fila se actualiza - esta es una característica deliberada de este tipo de datos.

DATETIME Por otro lado, no tiene este comportamiento extraño, es completamente normal.

La respuesta: created debe haber DATETIME, pero debido a this bug, también es necesario un disparador, así:

CREATE TABLE IF NOT EXISTS mytable (
    `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    `updated` TIMESTAMP, -- This will be updated to now(), if you don't set it or set it to null 
    `created` DATETIME NOT NULL, -- This will never be magically updated once written 
    `deleted` TINYINT DEFAULT 0, 
    `notes` TEXT DEFAULT '', 
    `description` VARCHAR(100) 
) TYPE=innodb; 

DELIMITER ~ 
CREATE TRIGGER mytable_insert_trigger 
BEFORE INSERT ON mytable 
FOR EACH ROW BEGIN 
    SET NEW.created = CURRENT_TIMESTAMP; 
END;~ 
DELIMITER ; 

insert into mytable (notes) values ('test'); 
select * from mytable; 
+----+---------------------+---------------------+---------+-------+-------------+ 
| id | updated    | created    | deleted | notes | description | 
+----+---------------------+---------------------+---------+-------+-------------+ 
| 1 | 2011-07-05 11:48:02 | 2011-07-05 11:48:02 |  0 | test | NULL  | 
+----+---------------------+---------------------+---------+-------+-------------+ 
+0

del mismo modo que hay una manera ingeniosa de hacer que 'updated' se restablezca automáticamente en cada actualización, el problema es cómo configurar' created' en la inserción sin agregarlo explícitamente a cada instrucción de inserción. –

+0

Correcto bien: corregido para reparar – Bohemian

+0

Como se indica en la respuesta de @Dark Slipstream anterior, NOW() no funciona con DATETIME. –

1

alternativa es cambiar el orden de la columna de marca de tiempo

O

valor Por omisión primera columna como ésta

ALTER TABLE `tblname` CHANGE `first_timestamp_column` 
    `first_timestamp_column` TIMESTAMP NOT NULL DEFAULT 0; 

Reference

Cuestiones relacionadas