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.
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