Comment définissez-vous une valeur par défaut pour une colonne MySQL Datetime?

898

Comment définissez-vous une valeur par défaut pour une colonne MySQL Datetime?

Dans SQL Server, c'est getdate(). Quel est l'équivalent pour MySQL? J'utilise MySQL 5.x si c'est un facteur.

Brian Boatright
la source
4
J'utilise CURRENT_TIMESTAMP dans ma table mysql (pas dans la requête), cela peut aussi être utile.
Ruben
15
Cette fonctionnalité a maintenant été ajoutée à MySQL 5.6.5. J'espère que cela aide quelqu'un. Optimize-this.blogspot.co.uk/2012/04/…
GhostInTheSecureShell
@GhostInTheSecureShell a tout à fait la mission de l'installer, au moins sur Debian, mais certainement une fonctionnalité impressionnante. Je pense que finalement toutes ces "deux questions CURRENT_TIMESTAMP" seront atténuées!
Marc DiMillo
c'est la fonction now () ou bien vous pouvez faire avec les paramètres par défaut au niveau de la colonne.
Anshul Sharma

Réponses:

862

EDIT IMPORTANT: Il est désormais possible d'y parvenir avec les champs DATETIME depuis MySQL 5.6.5 , jetez un œil à l' autre post ci-dessous ...

Les versions précédentes ne peuvent pas faire cela avec DATETIME ...

Mais vous pouvez le faire avec 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: SI vous définissez une colonne avec CURRENT_TIMESTAMP ON par défaut, vous devrez TOUJOURS spécifier une valeur pour cette colonne ou la valeur se réinitialisera automatiquement à "now ()" lors de la mise à jour. Cela signifie que si vous ne voulez pas que la valeur change, votre instruction UPDATE doit contenir "[votre nom de colonne] = [votre nom de colonne]" (ou une autre valeur) ou la valeur deviendra "maintenant ()". Bizarre, mais vrai. J'espère que ça aide. J'utilise 5.5.56-MariaDB **

sebthebert
la source
400
il est important de noter que datetime a une plage de 1000 à 9999, mais la plage d'horodatage n'est que de 1970 à 2038 . cela peut être un problème si votre système doit stocker des dates de naissance, ou si vous devez gérer quelque chose comme le plan de paiement pour une hypothèque de 30 ans. dev.mysql.com/doc/refman/5.0/en/datetime.html
Kip
13
Faites également attention à l'horodatage car il se met à jour automatiquement comme par magie ... voir la réponse suivante stackoverflow.com/a/1483959/233906
Cerber
6
Il est possible de la version 5.6.5, voir la réponse de Gustav ci - dessous (je me rends compte de votre réponse a été publiée lorsque MySQL était encore 5,0!)
e2-e4
4
@Kip, Salut, est-il possible d'avoir une valeur par défaut pour une DATEcolonne? (pas une datetimecolonne).
Sajib Acharya
ti ne semble pas être possible pour les colonnes DATE: vous devez utiliser le type de données DATETIME
Fabio Napodano
599

Dans la version 5.6.5, il est possible de définir une valeur par défaut sur une colonne datetime, et même de créer une colonne qui se mettra à jour lorsque la ligne sera mise à jour. La définition du type:

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

Référence: http://optimize-this.blogspot.com/2012/04/datetime-default-now-finally-available.html

Gustav Bertram
la source
3
Valeur par défaut non valide pour 'menu_creation_time'
Fernando Trindade
2
@FernandoTrindade Vous avez besoin de MySQL version 5.6.5 ou ultérieure. Vous pouvez le voir fonctionner ici: sqlfiddle.com/#!9/dd2be
Gustav Bertram
1
@GustavBertram, j'utilise la version 5.6.22, mais j'ai quand même eu l'erreur suivante: CREATE TABLE tbl (InsertDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, UpdateDate TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP (6)); Code d'erreur: 1294. Clause ON UPDATE non valide pour la colonne 'UpdateDate'
Manish Sapkal
@ManishSapkal Vous utilisez un TIMESTAMP, pas un DATETIME. Aussi, ne le mettez pas NULL.
Gustav Bertram
1
Je pense que la syntaxe "ON UPDATE" est incorrecte. Selon dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html, cela devrait êtredt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Dan Bough
148

MySQL ( avant la version 5.6.5 ) ne permet pas aux fonctions d'être utilisées pour les valeurs DateTime par défaut. TIMESTAMP ne convient pas en raison de son comportement étrange et n'est pas recommandé pour une utilisation en tant que données d'entrée. (Voir Valeurs par défaut du type de données MySQL .)

Cela dit, vous pouvez accomplir cela en créant un déclencheur .

J'ai une table avec un champ DateCreated de type DateTime. J'ai créé un déclencheur sur cette table "Before Insert" et " SET NEW.DateCreated=NOW()" et cela fonctionne très bien.

J'espère que cela aide quelqu'un.

Stephan Unrau
la source
21
CRÉER UN DÉCLENCHEUR trigger_foo_SetCreatedAt AVANT D'INSERER SUR foo POUR CHAQUE ENSEMBLE DE RANGÉES NEW.created_at = UTC_TIMESTAMP ();
kgriffs
5
Il vaut probablement mieux utiliser un horodatage qu'un déclencheur pour une raison future (maintenance). C'est un cas d'utilisation trop trivial pour un déclencheur, bien que ce soit une solution.
getWeberForStackExchange
8
Vous souhaiterez probablement définir la valeur par défaut uniquementIF NEW.created_at IS NOT NULL
Petr Peller
132

Pour moi, l'approche déclencheur a fonctionné le mieux, mais j'ai trouvé un problème avec l'approche. Considérez le déclencheur de base pour définir un champ de date à l'heure actuelle lors de l'insertion:

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

C'est généralement génial, mais disons que vous souhaitez définir le champ manuellement via l'instruction INSERT, comme suit:

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

Ce qui se passe, c'est que le déclencheur écrase immédiatement la valeur fournie pour le champ, et donc la seule façon de définir une heure non courante est une instruction UPDATE de suivi - beurk! Pour remplacer ce comportement lorsqu'une valeur est fournie, essayez ce déclencheur légèrement modifié avec l'opérateur IFNULL:

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

Cela donne le meilleur des deux mondes: vous pouvez fournir une valeur pour votre colonne de date et cela prendra, sinon il sera par défaut à l'heure actuelle. C'est toujours un ghetto par rapport à quelque chose de propre comme DEFAULT GETDATE () dans la définition du tableau, mais nous nous rapprochons!

John Larson
la source
5
+1 pour avoir reconnu la mise en garde avec l'écrasement des valeurs utilisateur explicites lors de l'insertion.
Kip
2
Personnellement, je pense que c'est la meilleure façon de procéder. TIMESTAMP a en effet un comportement étrange et je n'écrirais jamais de code qui a une limitation de 2038 ans.
Eric
Tant pis, je l'ai compris. Vous avez oublié de définir le champ à autoriser NULL. Plus d'avertissement.
Kaji
Les déclencheurs sont mauvais! Ne les utilisez que lorsqu'il n'y a pas d'autre moyen de faire quelque chose. Mieux vaut passer à l'id 5.6.x que vous pouvez plutôt que d'utiliser un déclencheur.
ksymeon
4
Dans MySQL 5.5, IFNULL ne fonctionne pas le DATETIME; en utilisant le déclencheur ci-dessus, le dateAddedaffichera tout '0000-00-00 00:00:00'. Utiliser ceci fait l'affaire: `POUR CHAQUE RANG SI SI NEW.dateAdded = 0 ALORS REGLER NEW.dateAdded = NOW (); FIN SI; `
Kenney
28

J'ai pu résoudre ce problème en utilisant cette instruction alter sur ma table qui avait deux champs 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;

Cela fonctionne comme vous vous attendez à ce que la fonction now () fonctionne. L'insertion de valeurs nulles ou l'ignorance des champs created_dt et updated_dt donne une valeur d'horodatage parfaite dans les deux champs. Toute mise à jour de la ligne modifie le updated_dt. Si vous insérez des enregistrements via le navigateur de requêtes MySQL, vous avez besoin d'une étape supplémentaire, un déclencheur pour gérer le created_dt avec un nouvel horodatage.

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

Le déclencheur peut être ce que vous voulez. J'aime juste la convention de dénomination [trig] _ [my_table_name] _ [insert]

utilisateur188217
la source
Je voulais dire, si vous insérez manuellement des enregistrements via le navigateur de requêtes MySQL via la grille sans instruction insert (), le déclencheur est nécessaire. Si vous utilisez toujours une instruction d'insertion, le déclencheur est complètement inutile.
Oups! Je voulais dire que le déclencheur (nom) peut être ce que vous voulez qu'il soit parce que le nom du déclencheur n'affecte pas du tout la fonctionnalité. La plupart des gens le savent, mais certains nouveaux
Oui, désolé pour le manque de sauts de ligne. Utilisez les points-virgules pour marquer la fin de chaque ligne.
24

Vous pouvez utiliser des déclencheurs pour faire ce genre de choses.

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;
Donald
la source
18

Pour tous ceux qui ont perdu courage en essayant de définir une valeur DATETIME par défaut dans MySQL , je sais exactement ce que vous ressentez / ressentez. Voici donc:

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

Observez attentivement que je n'ai pas ajouté de guillemets simples / guillemets doubles autour du 0

Je saute littéralement après avoir résolu celui-ci: D

Augiwan
la source
8
Il n'insère pas l'heure actuelle. Il insérera «0000-00-00 00:00:00».
Pit Digger
8
Je n'ai pas dit que cela règle l'heure actuelle. Beaucoup de ppl essayaient / essayent de définir une valeur zéro par défaut, mais cela ne fonctionne tout simplement pas. Nous devons éliminer les citations. Comme cette découverte a causé beaucoup de temps et de frustration, j'ai pensé à la partager avec la communauté. Des gens comme vous sont responsables de la perte d'intérêt des utilisateurs à partager des informations utiles avec d'autres personnes. Je ne vois vraiment aucune raison d'obtenir un -1! Peu importe.
Augiwan
3
La même chose pourrait être obtenue avec DATETIME NOT NULL.
Brendan Byrd
Il y a un autre caractère `à l'intérieur de l'exemple de commande sql, que je ne peux pas modifier, car il ne s'agit que d'un seul caractère.
quapka
votre code n'a pas fonctionné pour moi, voici ce qui a fonctionnéALTER TABLE zones MODIFY created datetime NOT NULL DEFAULT 0;
Smith
14

Si vous avez déjà créé la table, vous pouvez utiliser

Pour remplacer la valeur par défaut par l'heure de la date actuelle

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

Pour changer la valeur par défaut en '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';
Saveendra Ekanayake
la source
9

J'utilise MySql Server 5.7.11 et cette phrase:

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

est pas de travail. Mais ce qui suit:

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

fonctionne juste .

En tant que sidenote , il est mentionné dans les documents mysql :

Le type DATE est utilisé pour les valeurs avec une partie date mais pas de partie temps. MySQL récupère et affiche les valeurs DATE au format 'AAAA-MM-JJ'. La plage prise en charge est de '1000-01-01' à '9999-12-31'.

même s'ils disent aussi:

Les valeurs DATE, DATETIME ou TIMESTAMP non valides sont converties en la valeur «zéro» du type approprié («0000-00-00» ou «0000-00-00 00:00:00»).

Evhz
la source
8

Vous pouvez utiliser now () pour définir la valeur d'une colonne datetime, mais gardez à l'esprit que vous ne pouvez pas l'utiliser comme valeur par défaut.

KernelM
la source
4
vrai. J'ai juste essayé d'utiliser maintenant et j'ai obtenu une erreur "Code d'erreur: 1067. Valeur par défaut non valide.". alors quelle est la réponse? ;-)
Brian Boatright
C'est la meilleure solution pour compromettre les versions 5.5 et 5.6 de MySQL. Pour la version 5.5, prédéterminez la valeur de NOW()et utilisez-la ultérieurement pour l'insertion. Pour la version 5.6, définissez simplement NOW()la valeur par défaut.
Abel Callejo
8

Pour tous ceux qui utilisent la colonne TIMESTAMP comme solution, je veux seconder la limitation suivante du manuel:

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

"Le type de données TIMESTAMP a une plage de '1970-01-01 00:00:01' UTC à ' 2038-01-19 03:14:07 ' UTC. Il a des propriétés variables, selon la version de MySQL et le SQL mode d'exécution du serveur. Ces propriétés sont décrites plus loin dans cette section. "

Donc, cela cassera évidemment votre logiciel dans environ 28 ans.

Je crois que la seule solution du côté de la base de données est d'utiliser des déclencheurs comme mentionné dans d'autres réponses.

Fabien
la source
2
Et si MySQL était mis à jour dans 20 ans et que cette limitation était supprimée? Je ne sais pas si c'est possible mais juste une pensée.
NessDan
7

Lors de la définition de déclencheurs multilignes, il faut changer le délimiteur car le point-virgule sera pris par le compilateur MySQL comme fin de déclencheur et générer une erreur. par exemple

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

Voici comment le faire sur MySQL 5.1:

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

Je ne sais pas pourquoi vous devez entrer le nom de la colonne deux fois.

Samuel
la source
5
CHANGE sert également à renommer le champ. Le premier nom de colonne est «l'ancien», le deuxième nom de colonne est le «nouveau». Il semble redondant si vous ne changez pas le nom du champ. Si c'est trop déplaisant sur le plan esthétique, essayez MODIFIER.
John Gordon
5

Bien que vous ne puissiez pas le faire avec DATETIMEdans la définition par défaut, vous pouvez simplement incorporer une instruction select dans votre instruction insert comme ceci:

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

Notez le manque de guillemets autour de la table.

Pour MySQL 5.5

George
la source
3

Si vous essayez de définir la valeur par défaut comme NOW (), je ne pense pas que MySQL le supporte. Dans MySQL, vous ne pouvez pas utiliser une fonction ou une expression comme valeur par défaut pour tout type de colonne, à l'exception de la colonne de type de données TIMESTAMP, pour laquelle vous pouvez spécifier CURRENT_TIMESTAMP comme valeur par défaut.

Vijesh VP
la source
3

Je pense que c'est simple dans mysql puisque mysql la fonction intégrée appelée now () qui donne l'heure actuelle (heure de cet insert).

Votre requête devrait donc ressembler à

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

Je vous remercie.

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

Dans la requête ci-dessus pour créer «table de test», j'ai utilisé «1999-12-12 12:12:12» comme valeur par défaut pour la colonne DATETIME colname

Fathah Rehman P
la source
1

Utilisez le code suivant

DELIMITER $$

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

    DELIMITER ;
Rana Aalamgeer
la source
0

Si vous essayez de définir la valeur par défaut comme NOW (), MySQL prend en charge que vous devez changer le type de cette colonne TIMESTAMP au lieu de DATETIME. TIMESTAMP a la date et l'heure actuelles par défaut .. je pense que cela résoudra votre problème ..

Dhrumil Shah
la source
0

Prenez par exemple Si j'avais une table nommée 'site' avec une colonne created_at et une colonne update_at qui étaient toutes deux DATETIME et ont besoin de la valeur par défaut de now, je pourrais exécuter le sql suivant pour y parvenir.

ALTER TABLE `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 séquence d'instructions est importante car une table ne peut pas avoir deux colonnes de type TIMESTAMP avec des valeurs par défaut CUREENT TIMESTAMP

Joseph Persie
la source
0

Ceci est mon exemple déclencheur:

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

Lucas Moyano Angelini
la source
0

Fonctionne bien avec 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;
Gvs Akhil
la source
-3

Vous pouvez résoudre l'horodatage par défaut. Réfléchissez d'abord au jeu de caractères que vous utilisez, par exemple si u pris utf8, ce jeu de caractères prend en charge toutes les langues et si u pris laten1, ce jeu de caractères ne prend en charge que l'anglais. Si vous travaillez sous un projet, vous devez connaître le fuseau horaire du client et sélectionner votre zone client. Cette étape est obligatoire.

Srinivas
la source
2
Les colonnes DateTime ne peuvent pas avoir de valeurs par défaut. C'est une «fonctionnalité» documentée. Tous les développeurs n'ont pas accès à modifier leur encodage de caractères. Et définir le serveur sur le fuseau horaire de ses clients n'est généralement pas une possibilité, surtout lorsque les clients ne sont pas tous natifs d'une seule zone de fuseau horaire.
rlb.usa