Come si imposta un valore predefinito per una colonna MySQL Datetime?


898

Come si imposta un valore predefinito per una colonna MySQL Datetime?

In SQL Server lo è getdate(). Qual è l'equivalente per MySQL? Sto usando MySQL 5.x se questo è un fattore.


4
Uso CURRENT_TIMESTAMP nella mia tabella mysql (non nella query), forse anche questo può essere utile.
Ruben,

15
Questa funzione è stata ora aggiunta a MySQL 5.6.5. Spero che questo aiuti qualcuno. optimise-this.blogspot.co.uk/2012/04/…
GhostInTheSecureShell

@GhostInTheSecureShell ha la missione di installarlo, almeno su Debian, ma sicuramente una funzionalità fantastica. Penso che alla fine tutte queste "due CURRENT_TIMESTAMP" saranno alleviate!
Marc DiMillo,

ora è la funzione () oppure è possibile eseguire le impostazioni predefinite a livello di colonna.
Anshul Sharma,

Risposte:


862

MODIFICA IMPORTANTE: ora è possibile raggiungere questo obiettivo con i campi DATETIME da MySQL 5.6.5 , dai un'occhiata all'altro post qui sotto ...

Le versioni precedenti non potevano farlo con DATETIME ...

Ma puoi farlo con TIMESTAMP:

mysql> create table test (str varchar(32), ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.00 sec)

mysql> desc test;
+-------+-------------+------+-----+-------------------+-------+
| Field | Type        | Null | Key | Default           | Extra |
+-------+-------------+------+-----+-------------------+-------+
| str   | varchar(32) | YES  |     | NULL              |       | 
| ts    | timestamp   | NO   |     | CURRENT_TIMESTAMP |       | 
+-------+-------------+------+-----+-------------------+-------+
2 rows in set (0.00 sec)

mysql> insert into test (str) values ("demo");
Query OK, 1 row affected (0.00 sec)

mysql> select * from test;
+------+---------------------+
| str  | ts                  |
+------+---------------------+
| demo | 2008-10-03 22:59:52 | 
+------+---------------------+
1 row in set (0.00 sec)

mysql>

** CAVEAT: SE si definisce una colonna con CURRENT_TIMESTAMP ON come impostazione predefinita, sarà necessario SEMPRE specificare un valore per questa colonna o il valore si reimposterà automaticamente su "now ()" all'aggiornamento. Ciò significa che se non si desidera modificare il valore, l'istruzione UPDATE deve contenere "[nome colonna] = [nome colonna]" (o un altro valore) o il valore diventerà "now ()". Strano, ma vero. Spero che questo possa essere d'aiuto. Sto usando 5.5.56-MariaDB **


400
è importante notare che il datetime ha un intervallo di 1000-9999, ma l'intervallo per il timestamp è solo 1970-2038 . questo può essere un problema se il tuo sistema deve memorizzare le date di nascita o devi gestire qualcosa come il piano di pagamento per un mutuo di 30 anni. dev.mysql.com/doc/refman/5.0/en/datetime.html
Kip

13
Fai attenzione anche al timestamp in quanto si aggiorna automaticamente magicamente ... vedi la prossima risposta stackoverflow.com/a/1483959/233906
Cerber

6
Si è possibile a partire dalla versione 5.6.5, vedere la risposta di Gustav sotto (Mi rendo conto che la vostra risposta è stata pubblicata quando era ancora MySQL 5.0!)
e2-e4

4
@Kip, Ciao, è possibile avere un valore predefinito per una DATEcolonna? (non una datetimecolonna).
Sajib Acharya,

non ti sembra possibile per le colonne DATE: devi usare il tipo di dati DATETIME
Fabio Napodano,

599

Nella versione 5.6.5, è possibile impostare un valore predefinito su una colonna datetime e persino creare una colonna che verrà aggiornata quando la riga viene aggiornata. La definizione del tipo:

CREATE TABLE foo (
    `creation_time`     DATETIME DEFAULT CURRENT_TIMESTAMP,
    `modification_time` DATETIME ON UPDATE CURRENT_TIMESTAMP
)

Riferimento: http://optimize-this.blogspot.com/2012/04/datetime-default-now-finally-available.html


3
Valore predefinito non valido per "menu_creation_time"
Fernando Trindade,

2
@FernandoTrindade È necessario MySQL versione 5.6.5 o successive. Puoi vederlo funzionare qui: sqlfiddle.com/#!9/dd2be
Gustav Bertram

1
@GustavBertram, sto usando la versione 5.6.22, ma ho ancora ricevuto l'errore come segue: CREATE TABLE tbl (InsertDATE DATETIME NON NULL DEFAULT CURRENT_TIMESTAMP, UpdateDate TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP (6)); Codice errore: 1294. Clausola ON UPDATE non valida per la colonna "UpdateDate"
Manish Sapkal

@ManishSapkal Stai utilizzando un TIMESTAMP, non un DATETIME. Inoltre, non renderlo NULL.
Gustav Bertram,

1
Penso che la sintassi "ON UPDATE" sia sbagliata. Secondo dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html dovrebbe esseredt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Dan Bough,

148

MySQL ( prima della versione 5.6.5 ) non consente di utilizzare le funzioni per i valori DateTime predefiniti. TIMESTAMP non è adatto a causa del suo comportamento strano e non è raccomandato per l'uso come dati di input. (Vedi Impostazioni predefinite del tipo di dati MySQL .)

Detto questo, puoi farlo creando un trigger .

Ho una tabella con un campo DateCreated di tipo DateTime. Ho creato un trigger su quella tabella "Before Insert" e " SET NEW.DateCreated=NOW()" e funziona benissimo.

Spero che questo aiuti qualcuno.


21
CREA TRIGGER trigger_foo_SetCreatedA PRIMA DI INSERIRE SU foo PER OGNI RIGA SET NEW.created_at = UTC_TIMESTAMP ();
kgriffs,

5
Probabilmente stai meglio usando un timestamp che un trigger per la sanità mentale futura (manutenzione). Questo è un caso d'uso troppo banale per un trigger, sebbene sia una soluzione.
getWeberForStackExchange dal

8
Probabilmente vorrai impostare solo il valore predefinitoIF NEW.created_at IS NOT NULL
Petr Peller

132

Per me l'approccio trigger ha funzionato al meglio, ma ho trovato un problema con l'approccio. Considera il trigger di base per impostare un campo data sull'ora corrente al momento dell'inserimento:

CREATE TRIGGER myTable_OnInsert BEFORE INSERT ON `tblMyTable`
    FOR EACH ROW SET NEW.dateAdded = NOW();

Questo di solito è ottimo, ma supponiamo che tu voglia impostare il campo manualmente tramite l'istruzione INSERT, in questo modo:

INSERT INTO tblMyTable(name, dateAdded) VALUES('Alice', '2010-01-03 04:30:43');

Quello che succede è che il trigger sovrascrive immediatamente il valore fornito per il campo, e quindi l'unico modo per impostare un orario non corrente è un'istruzione UPDATE di follow-up - schifo! Per ignorare questo comportamento quando viene fornito un valore, provare questo trigger leggermente modificato con l'operatore IFNULL:

CREATE TRIGGER myTable_OnInsert BEFORE INSERT ON `tblMyTable`
    FOR EACH ROW SET NEW.dateAdded = IFNULL(NEW.dateAdded, NOW());

Questo offre il meglio di entrambi i mondi: puoi fornire un valore per la colonna della data e ci vorrà, altrimenti verrà impostato automaticamente l'ora corrente. È ancora ghetto rispetto a qualcosa di pulito come DEFAULT GETDATE () nella definizione della tabella, ma ci stiamo avvicinando!


5
+1 per riconoscere l'avvertenza con la sovrascrittura di valori utente espliciti su insert.
Kip

2
Personalmente penso che questo sia il modo migliore per andare. TIMESTAMP ha davvero un comportamento strano e non scriverei mai un codice che ha una limitazione di 2038 anni.
Eric

Non importa, l'ho capito. Ho dimenticato di impostare il campo per consentire NULL. Non ci sono più avvisi.
Kaji

I trigger sono cattivi! Usali solo quando non c'è altro modo di fare qualcosa. Meglio aggiornare a ID 5.6.x che puoi usare un trigger.
ksymeon,

4
In MySQL 5.5 IFNULL non funziona su DATETIME; usando il grilletto sopra dateAddedsi mostrerà tutto 'registrazione 00:00:00'. Usando questo fa il trucco: `FOR EACH ROW IF NEW.dateAdded = 0 THEN SET NEW.dateAdded = NOW (); END IF; `
Kenney,

28

Sono stato in grado di risolverlo usando questa istruzione alter sulla mia tabella che aveva due campi datetime.

ALTER TABLE `test_table`
  CHANGE COLUMN `created_dt` `created_dt` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
  CHANGE COLUMN `updated_dt` `updated_dt` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

Funziona come ci si aspetterebbe che funzioni now (). L'inserimento di valori null o l'ignoranza dei campi create_dt e updated_dt produce un valore di data / ora perfetto in entrambi i campi. Qualsiasi aggiornamento alla riga cambia updated_dt. Se si inseriscono record tramite il browser di query MySQL, è necessario un altro passaggio, un trigger per la gestione di Created_dt con un nuovo timestamp.

CREATE TRIGGER trig_test_table_insert BEFORE INSERT ON `test_table`
    FOR EACH ROW SET NEW.created_dt = NOW();

Il trigger può essere quello che vuoi Mi piace solo la convenzione di denominazione [trig] _ [my_table_name] _ [insert]


Volevo dire che se si inseriscono manualmente i record tramite il browser di query MySQL tramite la griglia senza un'istruzione insert (), è necessario il trigger. Se si utilizza sempre un'istruzione insert, il trigger è completamente inutile.

Ops! Volevo dire che il trigger (nome) può essere quello che vuoi che sia perché il nome del trigger non influisce affatto sulla funzionalità. La maggior parte delle persone lo saprà, ma alcune persone nuove a MySQL potrebbero non saperlo ...

Yikes, mi dispiace per la mancanza di interruzioni di riga. Usa i punti e virgola per segnare la fine di ogni riga.

24

È possibile utilizzare i trigger per eseguire questo tipo di cose.

CREATE TABLE `MyTable` (
`MyTable_ID`  int UNSIGNED NOT NULL AUTO_INCREMENT ,
`MyData`  varchar(10) NOT NULL ,
`CreationDate`  datetime NULL ,
`UpdateDate`  datetime NULL ,
PRIMARY KEY (`MyTable_ID`)
)
;

CREATE TRIGGER `MyTable_INSERT` BEFORE INSERT ON `MyTable`
FOR EACH ROW BEGIN
        -- Set the creation date
    SET new.CreationDate = now();

        -- Set the udpate date
    Set new.UpdateDate = now();
END;

CREATE TRIGGER `MyTable_UPDATE` BEFORE UPDATE ON `MyTable`
FOR EACH ROW BEGIN
        -- Set the udpate date
    Set new.UpdateDate = now();
END;

18

Per tutti coloro che hanno perso la testa cercando di impostare un valore DATETIME predefinito in MySQL , so esattamente come ti senti / senti. Quindi ecco qui:

ALTER TABLE  `table_name` CHANGE `column_name` DATETIME NOT NULL DEFAULT 0

Osservare attentamente che non ho aggiunto virgolette singole / doppie tra 0

Sto letteralmente saltando dopo aver risolto questo: D


8
Non inserisce l'ora non corrente. Inserirà "registrazione 00:00:00".
Pit Digger,

8
Non ho detto che imposta l'ora corrente. Molti ppl stavano / stanno provando a impostare un valore zero predefinito, ma non funziona. Dobbiamo eliminare le virgolette. Dato che questa scoperta ha causato molto tempo e frustrazione, ho pensato di condividerla con la comunità. Le persone come te sono responsabili per gli utenti che perdono interesse a condividere informazioni utili con altre persone. Davvero non vedo alcun motivo per ottenere un -1! Qualunque cosa.
Augiwan,

3
Lo stesso potrebbe essere ottenuto con DATETIME NOT NULL.
Brendan Byrd,

C'è un altro carattere `all'interno del comando sql di esempio, che non posso modificare, dato che è solo la modifica di un carattere.
quapka,

il tuo codice non ha funzionato per me, ecco cosa ha funzionatoALTER TABLE zones MODIFY created datetime NOT NULL DEFAULT 0;
Smith


14

Se hai già creato la tabella, puoi usarla

Per modificare il valore predefinito alla data corrente

ALTER TABLE <TABLE_NAME> 
CHANGE COLUMN <COLUMN_NAME> <COLUMN_NAME> DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;

Per modificare il valore predefinito in '2015-05-11 13:01:01'

ALTER TABLE <TABLE_NAME> 
CHANGE COLUMN <COLUMN_NAME> <COLUMN_NAME> DATETIME NOT NULL DEFAULT '2015-05-11 13:01:01';


9

Sto eseguendo MySql Server 5.7.11 e questa frase:

ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '0000-00-00 00:00:00'

è non lavorare. Ma quanto segue:

ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '1000-01-01 00:00:00'

funziona e basta .

Come sidenote , è menzionato nei documenti mysql :

Il tipo DATE viene utilizzato per i valori con una parte della data ma nessuna parte dell'ora. MySQL recupera e visualizza i valori DATA in formato 'AAAA-MM-GG'. L'intervallo supportato è compreso tra '1000-01-01' e '9999-12-31'.

anche se dicono anche:

I valori DATE, DATETIME o TIMESTAMP non validi vengono convertiti nel valore "zero" del tipo appropriato ("registrazione" o "registrazione 00:00:00").


8

Puoi usare now () per impostare il valore di una colonna datetime, ma tieni presente che non puoi usarlo come valore predefinito.


4
vero. Ho appena provato a utilizzare ora e ho ricevuto un errore "Codice errore: 1067. Valore predefinito non valido.". quindi qual è la risposta? ;-)
Brian Boatright,

Questa è la soluzione migliore per compromettere le versioni MySQL 5.5 e 5.6. Per la versione 5.5, predeterminare il valore NOW()e utilizzarlo in seguito per l'inserimento. Per la versione 5.6, impostare semplicemente NOW()come valore predefinito.
Abel Callejo,

8

Per tutti coloro che usano la colonna TIMESTAMP come soluzione, voglio secondare la seguente limitazione dal manuale:

http://dev.mysql.com/doc/refman/5.0/en/datetime.html

"Il tipo di dati TIMESTAMP ha un intervallo compreso tra '1970-01-01 00:00:01' UTC e ' 2038-01-19 03:14:07 ' UTC. Ha proprietà variabili, a seconda della versione di MySQL e di SQL modalità in cui è in esecuzione il server. Queste proprietà sono descritte più avanti in questa sezione. "

Quindi questo ovviamente romperà il tuo software in circa 28 anni.

Credo che l'unica soluzione dal lato del database sia usare i trigger come menzionato in altre risposte.


2
Cosa succederebbe se MySQL fosse aggiornato tra 20 anni e tale limitazione fosse rimossa? Non sono sicuro che sia possibile, ma solo un pensiero.
NessDan,

7

Mentre si definiscono i trigger multilinea, è necessario modificare il delimitatore poiché il compilatore MySQL prenderà il punto e virgola come fine del trigger e genererà errori. per esempio

DELIMITER //
CREATE TRIGGER `MyTable_UPDATE` BEFORE UPDATE ON `MyTable`
FOR EACH ROW BEGIN
        -- Set the udpate date
    Set new.UpdateDate = now();
END//
DELIMITER ;

5

Ecco come farlo su MySQL 5.1:

ALTER TABLE `table_name` CHANGE `column_name` `column_name` 
TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;

Non ho idea del perché devi inserire due volte il nome della colonna.


5
CHANGE serve anche a rinominare il campo. Il nome della prima colonna è il "vecchio", il nome della seconda colonna è il "nuovo". Sembra ridondante se non si modifica il nome del campo. Se è esteticamente spiacevole, prova a MODIFICARE.
John Gordon,

5

Sebbene non sia possibile farlo con DATETIMEla definizione predefinita, puoi semplicemente incorporare un'istruzione select nell'istruzione insert in questo modo:

INSERT INTO Yourtable (Field1, YourDateField) VALUES('val1', (select now()))

Nota la mancanza di virgolette attorno al tavolo.

Per MySQL 5.5


3

Se stai cercando di impostare il valore predefinito come NOW (), non credo che MySQL lo supporti. In MySQL, non è possibile utilizzare una funzione o un'espressione come valore predefinito per qualsiasi tipo di colonna, ad eccezione della colonna del tipo di dati TIMESTAMP, per la quale è possibile specificare CURRENT_TIMESTAMP come predefinito.


3

Penso che sia semplice in mysql poiché mysql la funzione integrata chiamata now () che fornisce l'ora corrente (ora dell'inserimento).

Quindi la tua query dovrebbe apparire in modo simile

CREATE TABLE defaultforTime(
    `creation_time`     DATETIME DEFAULT CURRENT_TIMESTAMP,
    `modification_time` DATETIME default now()
);

Grazie.


2
CREATE TABLE `testtable` (
    `id` INT(10) NULL DEFAULT NULL,
    `colname` DATETIME NULL DEFAULT '1999-12-12 12:12:12'
)

Nella query sopra per creare 'testtable', ho usato '1999-12-12 12:12:12' come valore predefinito per la colonna DATETIME colname


1

Usa il seguente codice

DELIMITER $$

    CREATE TRIGGER bu_table1_each BEFORE UPDATE ON table1 FOR EACH ROW
    BEGIN
      SET new.datefield = NOW();
    END $$

    DELIMITER ;

0

Se stai cercando di impostare il valore predefinito come NOW (), MySQL supporta la necessità di modificare il tipo di quella colonna TIMESTAMP anziché DATETIME. TIMESTAMP ha la data e l'ora correnti come predefinite..penso che risolverà il tuo problema ..


0

Ad esempio, se avessi una tabella denominata "site" con una colonna create_at e update_at che erano entrambi DATETIME e richiedessero il valore predefinito di adesso, potrei eseguire il seguente sql per raggiungere questo obiettivo.

TABELLA ALTER `site` CHANGE` Created_at` `Created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;

ALTER TABLE `site` CHANGE` Created_at` `Created_at` DATETIME NULL DEFAULT NULL;

ALTER TABLE `site` CHANGE` updated_at` `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;

ALTER TABLE `site` CHANGE` updated_at` `updated_at` DATETIME NULL DEFAULT NULL;

La sequenza di istruzioni è importante perché una tabella non può avere due colonne di tipo TIMESTAMP con i valori predefiniti di CUREENT TIMESTAMP


0

Questo è il mio esempio di innesco:

/************ ROLE ************/
drop table if exists `role`;
create table `role` (
    `id_role` bigint(20) unsigned not null auto_increment,
    `date_created` datetime,
    `date_deleted` datetime,
    `name` varchar(35) not null,
    `description` text,
    primary key (`id_role`)
) comment='';

drop trigger if exists `role_date_created`;
create trigger `role_date_created` before insert
    on `role`
    for each row 
    set new.`date_created` = now();


0

Funziona bene con MySQL 8.x

CREATE TABLE `users` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `dateCreated` datetime DEFAULT CURRENT_TIMESTAMP,
      `dateUpdated` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`),
      UNIQUE KEY `mobile_UNIQUE` (`mobile`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-3

È possibile risolvere il timestamp predefinito. Innanzitutto considera quale set di caratteri stai usando, ad esempio, se hai preso utf8 questo set di caratteri supporta tutte le lingue e se hai preso laten1 questo set di caratteri supporta solo l'inglese. Setp successivo se stai lavorando con qualsiasi progetto, dovresti conoscere il fuso orario del cliente e selezionare di essere zona del cliente. Questo passaggio è obbligatorio.


2
Le colonne DateTime non possono avere valori predefiniti. È documentato "funzionalità". Non tutti gli sviluppatori hanno accesso a modificare la codifica dei caratteri. E impostare il server sul suo fuso orario client di solito non è una possibilità, specialmente quando i client non sono tutti nativi in ​​una singola area del fuso orario.
rlb.usa,
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.