Por que pode haver apenas uma coluna TIMESTAMP com CURRENT_TIMESTAMP na cláusula DEFAULT?

Por que pode haver apenas uma coluna TIMESTAMP com CURRENT_TIMESTAMP na cláusula DEFAULT ou ON UPDATE?

CREATE TABLE `foo` ( `ProductID` INT(10) UNSIGNED NOT NULL, `AddedDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `UpdatedDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=INNODB; 

O erro que resulta:

Código de erro: 1293

Definição de tabela incorreta; pode haver apenas uma coluna TIMESTAMP com CURRENT_TIMESTAMP na cláusula DEFAULT ou ON UPDATE

Esta limitação, que foi apenas devido a razões legadas de código, foi levantada em versões recentes do MySQL:

Mudanças no MySQL 5.6.5 (2012-04-10, Milestone 8)

Anteriormente, no máximo uma coluna TIMESTAMP por tabela poderia ser inicializada ou atualizada automaticamente para a data e hora atuais. Esta restrição foi levantada. Qualquer definição de coluna TIMESTAMP pode ter qualquer combinação de cláusulas DEFAULT CURRENT_TIMESTAMP e ON UPDATE CURRENT_TIMESTAMP. Além disso, essas cláusulas agora podem ser usadas com definições de coluna DATETIME. Para obter mais informações, consulte Inicialização e atualização automáticas para TIMESTAMP e DATETIME.

http://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-5.html

Eu também me perguntei isso há muito tempo. Eu procurei um pouco na minha história e acho que este post: http://lists.mysql.com/internals/34919 representa a posição semi-oficial do MySQL (antes da intervenção da Oracle;))

Em resumo:

essa limitação deriva apenas da maneira como esse recurso está atualmente implementado no servidor e não há outros motivos para sua existência.

Então, a explicação deles é “porque é implementada assim”. Não parece muito científico. Eu acho que tudo vem de algum código antigo. Isso é sugerido no tópico acima: “transferência de quando apenas o primeiro campo de registro de data e hora foi definido / atualizado automaticamente”.

Felicidades!

Podemos fornecer um valor padrão para o registro de data e hora para evitar esse problema.

Esta publicação fornece uma solução detalhada: http://gusiev.com/2009/04/update-and-create-timestamps-with-mysql/

 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() ); 

Observe que é necessário inserir valores nulos nas duas colunas durante a “inserção”:

 mysql> insert into test_table(stamp_created, stamp_updated) values(null, null); Query OK, 1 row affected (0.06 sec) mysql> select * from t5; +----+---------------------+---------------------+ | 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) 

De fato, uma falha de implementação.

A abordagem nativa no MySQL é atualizar uma data de criação você mesmo (se precisar) e o MySQL se preocupar com a data de update date ? update date : creation date do timestamp update date ? update date : creation date update date ? update date : creation date assim:

 CREATE TABLE tracked_data( `data` TEXT, `timestamp` TIMESTAMP, `creation_date` TIMESTAMP ) ENGINE=INNODB; 

Na criação Inserir NULL:

 INSERT INTO tracked_data(`data`,`creation_date`) VALUES ('creation..',NULL); 

Valores NULL para timestamp são interpretados como CURRENT_TIMESTAMP por padrão.

No MySQL, a primeira coluna TIMESTAMP de uma tabela obtém os atributos DEFAULT CURRENT_TIMESTAMP e ON UPDATE CURRENT_TIMESTAMP , se nenhum atributo for fornecido para ela. É por isso que a coluna TIMESTAMP com atributos deve vir primeiro ou você recebe o erro descrito neste tópico.

  1. Alterar tipos de dados de colunas para data e hora
  2. Definir gatilho

Tal como:

 DROP TRIGGER IF EXISTS `update_tablename_trigger`; DELIMITER // CREATE TRIGGER `update_tablename_trigger` BEFORE UPDATE ON `tablename` FOR EACH ROW SET NEW.`column_name` = NOW() // DELIMITER ; 

Bem, uma correção para você poderia ser colocá-lo no campo UpdatedDate e ter um triggersdor que atualiza o campo AddedDate com o valor UpdatedDate somente se AddedDate for null.

Combinando várias respostas:

No MySQL 5.5, DEFAULT CURRENT_TIMESTAMP e ON UPDATE CURRENT_TIMESTAMP não podem ser adicionados em DATETIME mas somente em TIMESTAMP .

Regras:

1) no máximo uma coluna TIMESTAMP por tabela pode ser automaticamente (ou manualmente [ My addition ]) inicializada ou atualizada para a data e hora atuais. (MySQL Docs).

Portanto, apenas um TIMESTAMP pode ter CURRENT_TIMESTAMP na cláusula DEFAULT ou ON UPDATE

2) A primeira coluna NOT NULL TIMESTAMP sem um valor DEFAULT explícito como created_date timestamp default '0000-00-00 00:00:00' receberá implicitamente uma DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP e, portanto, as colunas TIMESTAMP subsequentes não poderão receber CURRENT_TIMESTAMP em DEFAULT ou cláusula ON UPDATE

 CREATE TABLE `address` ( `id` int(9) NOT NULL AUTO_INCREMENT, `village` int(11) DEFAULT NULL, `created_date` timestamp default '0000-00-00 00:00:00', -- Since explicit DEFAULT value that is not CURRENT_TIMESTAMP is assigned for a NOT NULL column, -- implicit DEFAULT CURRENT_TIMESTAMP is avoided. -- So it allows us to set ON UPDATE CURRENT_TIMESTAMP on 'updated_date' column. -- How does setting DEFAULT to '0000-00-00 00:00:00' instead of CURRENT_TIMESTAMP help? -- It is just a temporary value. -- On INSERT of explicit NULL into the column inserts current timestamp. -- `created_date` timestamp not null default '0000-00-00 00:00:00', // same as above -- `created_date` timestamp null default '0000-00-00 00:00:00', -- inserting 'null' explicitly in INSERT statement inserts null (Ignoring the column inserts the default value)! -- Remember we need current timestamp on insert of 'null'. So this won't work. -- `created_date` timestamp null , // always inserts null. Equally useless as above. -- `created_date` timestamp default 0, // alternative to '0000-00-00 00:00:00' -- `created_date` timestamp, -- first 'not null' timestamp column without 'default' value. -- So implicitly adds DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP. -- Hence cannot add 'ON UPDATE CURRENT_TIMESTAMP' on 'updated_date' column. `updated_date` timestamp null on update current_timestamp, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=132 DEFAULT CHARSET=utf8; 

 INSERT INTO address (village,created_date) VALUES (100,null); 

 mysql> select * from address; +-----+---------+---------------------+--------------+ | id | village | created_date | updated_date | +-----+---------+---------------------+--------------+ | 132 | 100 | 2017-02-18 04:04:00 | NULL | +-----+---------+---------------------+--------------+ 1 row in set (0.00 sec) 

 UPDATE address SET village=101 WHERE village=100; 

 mysql> select * from address; +-----+---------+---------------------+---------------------+ | id | village | created_date | updated_date | +-----+---------+---------------------+---------------------+ | 132 | 101 | 2017-02-18 04:04:00 | 2017-02-18 04:06:14 | +-----+---------+---------------------+---------------------+ 1 row in set (0.00 sec) 

Outra opção (Mas updated_date é a primeira coluna):

 CREATE TABLE `address` ( `id` int(9) NOT NULL AUTO_INCREMENT, `village` int(11) DEFAULT NULL, `updated_date` timestamp null on update current_timestamp, `created_date` timestamp not null , -- implicit default is '0000-00-00 00:00:00' from 2nd timestamp onwards -- `created_date` timestamp not null default '0000-00-00 00:00:00' -- `created_date` timestamp -- `created_date` timestamp default '0000-00-00 00:00:00' PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=132 DEFAULT CHARSET=utf8; 

Tente isto:

 CREATE TABLE `test_table` ( `id` INT( 10 ) NOT NULL, `created_at` TIMESTAMP NOT NULL DEFAULT 0, `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE = INNODB; 

Esta é a limitação na versão 5.5 do MYSQL. Você precisa atualizar a versão para 5.6.

 Error 

Eu estava recebendo este erro ao adicionar uma tabela no MYSQL

Definição de tabela incorreta; pode haver apenas uma coluna TIMESTAMP com CURRENT_TIMESTAMP na cláusula DEFAULT ou ON UPDATE Meu novo MYSQL

mesa parece algo como isto.

create table table_name (col1 int (5) auto_increment chave primária, col2 varchar (300), col3 varchar (500), col4 int (3), col5 tinyint (2), col6 timestamp padrão current_timestamp, col7 timestamp padrão current_timestamp na atualização current_timestamp, col8 tinyint (1) padrão 0, col9 tinyint (1) padrão 1);

Depois de algum tempo lendo sobre mudanças em diferentes versões MYSQL e alguns dos googling. Eu descobri que houve algumas mudanças que foram feitas na versão 5.6 do MYSQL sobre a versão 5.5.

Este artigo ajudará você a resolver o problema. http://www.oyewiki.com/MYSQL/Incorrect-table-definition-there-can-be-only-one-timestamp-column