Perché può esserci solo una colonna TIMESTAMP con CURRENT_TIMESTAMP nella clausola DEFAULT?


180

Perché può esserci solo una colonna TIMESTAMP con CURRENT_TIMESTAMP nella clausola DEFAULT o 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;

L'errore che risulta:

Codice errore: 1293

Definizione errata della tabella; può esserci solo una colonna TIMESTAMP con CURRENT_TIMESTAMP nella clausola DEFAULT o ON UPDATE


6
In realtà è molto peggio di quello che sembra essere il messaggio di errore. Non puoi definire una colonna con CURRENT_TIMESTAMPin DEFAULTo ON UPDATEclausola una volta che c'è una colonna con TIMESTAMPtipo di dati, non importa se ha una clausola aggiuntiva!
Nicolas Buduroi,

9
Quindi questo lavoro CREATE TABLE foo (created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_on TIMESTAMP)CREATE TABLE foo (updated_on TIMESTAMP, created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
:,

@NicolasBuduroi Non se la prima timestampcolonna è nullable cioè null. Se la prima timestampcolonna è not nullquindi per impostazione predefinita DEFAULT CURRENT_TIMESTAMPe ON UPDATE CURRENT_TIMESTAMPverrà aggiunta. stackoverflow.com/a/13544181/2859238
user104309

@NicolasBuduroi Anche se la prima timestampcolonna ha un valore predefinito esplicito impostato come default '0000-00-00 00:00:00'. Se la colonna è nullable o viene impostato esplicitamente il valore predefinito, allora DEFAULT CURRENT_TIMESTAMPe ON UPDATE CURRENT_TIMESTAMPNON verrà aggiunto
user104309

Mi piacerebbe davvero vedere una risposta sul perché? non come aggirarlo o come è risolto ora. Perché questo è mai stato implementato in questo modo? Sembra un modo totalmente semplice e non riesco a trovare alcun progetto / implementazione che potrebbe essere una ragione per questa restrizione. Voglio imparare come programmano le persone stupide, quindi per favore insegnami.
Lothar,

Risposte:


173

Questa limitazione, dovuta solo a motivi storici, legati al codice, è stata eliminata nelle recenti versioni di MySQL:

Modifiche in MySQL 5.6.5 (2012-04-10, Milestone 8)

In precedenza, al massimo una colonna TIMESTAMP per tabella poteva essere inizializzata o aggiornata automaticamente alla data e ora correnti. Questa limitazione è stata revocata. Qualsiasi definizione di colonna TIMESTAMP può avere qualsiasi combinazione di clausole DEFAULT CURRENT_TIMESTAMP e ON UPDATE CURRENT_TIMESTAMP. Inoltre, queste clausole ora possono essere utilizzate con le definizioni delle colonne DATETIME. Per ulteriori informazioni, vedere Inizializzazione e aggiornamento automatici per TIMESTAMP e DATETIME.

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


Controlla anche la risposta di @mooli di seguito. In realtà la prima colonna timestamp ha "default current_timestamp on update current_timestamp" impostato automaticamente (quindi dovrebbe essere chiamato aggiornato_at). Devi solo impostare Created_at manualmente al momento dell'inserimento.
Gismo Ranas,

cosa possiamo fare se il dump mysql appartiene a una versione 5.7 e l'installazione deve essere eseguita su un 5.4
otc

1
@otc, potresti modificare il dump o ricominciare con 5.4
Jasen

40

Mi sono anche chiesto tanto tempo fa. Ho cercato un po 'nella mia storia e penso che questo post: http://lists.mysql.com/internals/34919 rappresenti la posizione semi-ufficiale di MySQL (prima dell'intervento di Oracle;))

In breve:

questa limitazione deriva solo dal modo in cui questa funzione è attualmente implementata nel server e non ci sono altri motivi per la sua esistenza.

Quindi la loro spiegazione è "perché è implementata in questo modo". Non sembra molto scientifico. Immagino che provenga da un vecchio codice. Questo è suggerito nel thread sopra: "riporto da quando solo il primo campo timestamp è stato impostato / aggiornato automaticamente".

Saluti!


Wow, puzza davvero. Spero di vedere presto una soluzione.
BoltClock

46
Un'altra grande limitazione di MySQL per noi!
Nicolas Buduroi,

1
@gorn la soluzione più semplice / aggirare è quella di Scarlett di seguito.
Tihe

38

È possibile fornire un valore predefinito per il timestamp per evitare questo problema.

Questo post offre una soluzione dettagliata: 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() 
);

Si noti che è necessario inserire valori null in entrambe le colonne 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 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) 

16

Davvero un errore di implementazione.

L'approccio nativo a MySQL è quello di aggiornare la data di creazione da soli (se avete bisogno di uno) e hanno MySQL preoccupazione per il timestamp update date ? update date : creation date in questo modo:

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

Alla creazione, inserire NULL:

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

I valori NULL per il timestamp vengono interpretati come CURRENT_TIMESTAMP per impostazione predefinita.

In MySQL prima colonna timestamp di una tabella ottiene entrambi DEFAULT CURRENT_TIMESTAMPe ON UPDATE CURRENT_TIMESTAMPattributo, se attributi sono dati per esso. questo è il motivo per cui la colonna TIMESTAMP con gli attributi deve venire prima o si ottiene l'errore descritto in questo thread.


14
  1. Cambia i tipi di dati delle colonne in datetime
  2. Imposta trigger

Ad esempio:

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 ;

Ho sempre considerato questo metodo molto meno jankety rispetto alla funzionalità CURRENT_TIMESTAMP implementata per metà.
TehShrike,

1

Bene, una soluzione per te potrebbe essere quella di metterlo nel campo UpdatedDate e avere un trigger che aggiorna il campo AddedDate con il valore UpdatedDate solo se AddedDate è null.


1

Combinazione di varie risposte:

In MySQL 5.5 DEFAULT CURRENT_TIMESTAMPe ON UPDATE CURRENT_TIMESTAMPnon può essere aggiunto DATETIMEma solo su TIMESTAMP.

Regole:

1) al massimo una TIMESTAMPcolonna per tabella potrebbe essere inizializzata automaticamente (o manualmente [La mia aggiunta ]) o aggiornata alla data e ora correnti. (Documenti MySQL).

Quindi solo uno TIMESTAMPpuò avere CURRENT_TIMESTAMPin DEFAULTo ON UPDATEclausola

2) La prima NOT NULL TIMESTAMPcolonna senza un DEFAULTvalore esplicito come created_date timestamp default '0000-00-00 00:00:00'verrà implicitamente assegnata una DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPe quindi le TIMESTAMPcolonne successive non possono essere fornite o CURRENT_TIMESTAMPsulla clausolaDEFAULTON 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)

Altra opzione (Ma updated_dateè la prima colonna):

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;

0

Prova questo:

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;

3
Funzionerà ma non risolve il problema. Created_at è 0 che è un po 'inutile.
CompEng88,

@ ComputerEngineer88 Questa è la soluzione giusta per il vecchio server mysql. Dovresti impostare created_attu stesso la colonna. Penso che questo sia ciò che op vuole dire intenzionalmente.
Roger,

questa è esattamente la soluzione ufficiale, documentata qui dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html
Rangi Lin

0

Questa è la limitazione nella versione MYSQL 5.5. Devi aggiornare la versione alla 5.6.

Error

Stavo ottenendo questo errore durante l'aggiunta di una tabella in MYSQL

Definizione errata della tabella; può esserci solo una colonna TIMESTAMP con CURRENT_TIMESTAMP nella clausola DEFAULT o ON UPDATE Il mio nuovo MYSQL

la tabella è simile a questa.

crea tabella table_name (col1 int (5) auto_increment chiave primaria, col2 varchar (300), col3 varchar (500), col4 int (3), col5 tinyint (2), col6 timestamp default current_timestamp, col7 timestamp default current_timestamp sull'aggiornamento current_timestamp, col8 tinyint (1) predefinito 0, col9 tinyint (1) predefinito 1);

Dopo un po 'di tempo a leggere sui cambiamenti nelle diverse versioni di MYSQL e su alcuni dei googling. Ho scoperto che sono state apportate alcune modifiche in MYSQL versione 5.6 rispetto alla versione 5.5.

Questo articolo ti aiuterà a risolvere il problema. http://www.oyewiki.com/MYSQL/Incorrect-table-definition-there-can-be-only-one-timestamp-column

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.