Wie legen Sie einen Standardwert für eine MySQL Datetime-Spalte fest?


898

Wie legen Sie einen Standardwert für eine MySQL Datetime-Spalte fest?

In SQL Server ist es getdate(). Was ist das Äquivalent für MySQL? Ich verwende MySQL 5.x, wenn dies ein Faktor ist.


4
Ich verwende CURRENT_TIMESTAMP in meiner MySQL-Tabelle (nicht in der Abfrage), vielleicht kann dies auch hilfreich sein.
Ruben

15
Diese Funktion wurde jetzt zu MySQL 5.6.5 hinzugefügt. Hoffe das hilft jemandem. optimize-this.blogspot.co.uk/2012/04/…
GhostInTheSecureShell

@GhostInTheSecureShell ist die Mission, es zu installieren, zumindest auf Debian, aber definitiv eine großartige Funktion. Ich denke, irgendwann werden all diese "zwei CURRENT_TIMESTAMP" -Fragen gelindert!
Marc DiMillo

Es ist jetzt () oder Sie können die Standardeinstellungen auf Spaltenebene vornehmen.
Anshul Sharma

Antworten:


862

WICHTIGE BEARBEITUNG : Dies ist jetzt mit DATETIME-Feldern seit MySQL 5.6.5 möglich . Schauen Sie sich den anderen Beitrag unten an ...

Frühere Versionen können das mit DATETIME nicht ...

Aber Sie können es mit TIMESTAMP tun:

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: Wenn Sie eine Spalte mit CURRENT_TIMESTAMP ON als Standard definieren, müssen Sie IMMER einen Wert für diese Spalte angeben, da sich der Wert beim Update automatisch auf "now ()" zurücksetzt. Dies bedeutet, dass Ihre UPDATE-Anweisung "[Ihr Spaltenname] = [Ihr Spaltenname]" (oder einen anderen Wert) enthalten muss, wenn Sie nicht möchten, dass sich der Wert ändert. Andernfalls wird der Wert zu "now ()". Seltsam, aber wahr. Ich hoffe das hilft. Ich benutze 5.5.56-MariaDB **


400
Es ist wichtig zu beachten, dass datetime einen Bereich von 1000-9999 hat, der Bereich für den Zeitstempel jedoch nur 1970-2038 . Dies kann ein Problem sein, wenn Ihr System Geburtsdaten speichern muss oder Sie so etwas wie den Zahlungsplan für eine 30-jährige Hypothek verwalten müssen. dev.mysql.com/doc/refman/5.0/en/datetime.html
Kip

13
Seien Sie auch vorsichtig mit dem Zeitstempel, da dieser automatisch aktualisiert wird ... siehe nächste Antwort stackoverflow.com/a/1483959/233906
Cerber

6
Es ist ab Version 5.6.5 möglich, siehe Gustavs Antwort unten (mir ist klar, dass Ihre Antwort veröffentlicht wurde, als MySQL noch 5.0 war!)
e2-e4

4
@Kip, Hallo, ist es möglich, einen Standardwert für eine DATESpalte zu haben? (keine datetimeSpalte).
Sajib Acharya

ti scheint für DATE-Spalten nicht möglich zu sein: Sie müssen den Datentyp DATETIME verwenden
Fabio Napodano

599

In Version 5.6.5 ist es möglich, einen Standardwert für eine Datums- / Uhrzeitspalte festzulegen und sogar eine Spalte zu erstellen, die aktualisiert wird, wenn die Zeile aktualisiert wird. Die Typdefinition:

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

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


3
Ungültiger Standardwert für 'menu_creation_time'
Fernando Trindade

2
@FernandoTrindade Sie benötigen MySQL Version 5.6.5 oder höher. Sie können es hier sehen: sqlfiddle.com/#!9/dd2be
Gustav Bertram

1
@GustavBertram, ich verwende Version 5.6.22, habe aber trotzdem folgende Fehlermeldung erhalten: CREATE TABLE tbl (InsertDate DATETIME NICHT NULL DEFAULT CURRENT_TIMESTAMP, UpdateDate TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP (6)); Fehlercode: 1294. Ungültige ON UPDATE-Klausel für die Spalte 'UpdateDate'
Manish Sapkal

@ManishSapkal Sie verwenden einen TIMESTAMP, keinen DATETIME. Machen Sie es auch nicht NULL.
Gustav Bertram

1
Ich denke, die "ON UPDATE" -Syntax ist falsch. Laut dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html sollte es seindt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Dan Bough

148

In MySQL ( vor Version 5.6.5 ) können Funktionen nicht für Standard-DateTime-Werte verwendet werden. TIMESTAMP ist aufgrund seines ungewöhnlichen Verhaltens nicht geeignet und wird nicht zur Verwendung als Eingabedaten empfohlen. (Siehe MySQL-Datentyp-Standardeinstellungen .)

Sie können dies jedoch erreichen, indem Sie einen Trigger erstellen .

Ich habe eine Tabelle mit einem DateCreated-Feld vom Typ DateTime. Ich habe einen Trigger für diese Tabelle "Before Insert" und " SET NEW.DateCreated=NOW()" erstellt und es funktioniert großartig.

Ich hoffe das hilft jemandem.


21
CREATE TRIGGER trigger_foo_SetCreatedAt VOR EINFÜGEN IN foo FÜR JEDEN REIHENSATZ NEW.created_at = UTC_TIMESTAMP ();
Kgriffs

5
Sie sind wahrscheinlich besser dran, einen Zeitstempel als einen Auslöser für zukünftige Gesundheit (Wartung) zu verwenden. Dies ist ein zu trivialer Anwendungsfall für einen Trigger, obwohl dies eine Lösung ist.
getWeberForStackExchange

8
Sie werden wahrscheinlich nur den Standardwert einstellen wollenIF NEW.created_at IS NOT NULL
Petr Peller

132

Für mich hat der Trigger-Ansatz am besten funktioniert, aber ich habe einen Haken bei dem Ansatz gefunden. Betrachten Sie den grundlegenden Auslöser, um ein Datumsfeld beim Einfügen auf die aktuelle Uhrzeit festzulegen:

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

Dies ist normalerweise großartig, aber sagen Sie, Sie möchten das Feld manuell über die INSERT-Anweisung festlegen, wie folgt:

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

Was passiert ist, dass der Trigger Ihren angegebenen Wert für das Feld sofort überschreibt. Die einzige Möglichkeit, eine nicht aktuelle Zeit festzulegen, ist eine nachfolgende UPDATE-Anweisung - yuck! Versuchen Sie diesen leicht geänderten Trigger mit dem IFNULL-Operator, um dieses Verhalten zu überschreiben, wenn ein Wert angegeben wird:

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

Dies bietet das Beste aus beiden Welten: Sie können einen Wert für Ihre Datumsspalte angeben, der dauert, andernfalls wird standardmäßig die aktuelle Uhrzeit verwendet. Es ist immer noch ein Ghetto im Vergleich zu etwas Sauberem wie DEFAULT GETDATE () in der Tabellendefinition, aber wir kommen näher!


5
+1 zum Bestätigen der Einschränkung beim Überschreiben expliziter Benutzerwerte beim Einfügen.
Kip

2
Ich persönlich denke, das ist der beste Weg. TIMESTAMP hat in der Tat ein merkwürdiges Verhalten und ich würde niemals Code schreiben, der eine Beschränkung von 2038 Jahren hat.
Eric

Egal, ich habe es herausgefunden. Ich habe vergessen, das zuzulassende Feld festzulegen NULL. Keine Warnungen mehr.
Kaji

Auslöser sind böse! Verwenden Sie sie nur, wenn es keine andere Möglichkeit gibt, etwas zu tun. Besser ein Upgrade auf 5.6.x ID als einen Trigger verwenden.
Ksymeon

4
In MySQL 5.5 funktioniert IFNULL unter DATETIME nicht. Mit dem obigen Trigger dateAddedwerden alle '0000-00-00 00:00:00' angezeigt. Dies macht den Trick: `FÜR JEDE REIHE, WENN NEW.dateAdded = 0 THEN SET NEW.dateAdded = NOW (); END IF; `
Kenney

28

Ich konnte dies mit dieser alter-Anweisung in meiner Tabelle lösen, die zwei datetime-Felder enthielt.

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;

Dies funktioniert so, wie Sie es von der Funktion now () erwarten würden. Das Einfügen von Nullen oder das Ignorieren der Felder "created_dt" und "updated_dt" führt in beiden Feldern zu einem perfekten Zeitstempelwert. Jede Aktualisierung der Zeile ändert die aktualisierte_dt. Wenn Sie Datensätze über den MySQL-Abfragebrowser einfügen, benötigen Sie einen weiteren Schritt, einen Trigger, um das erstellte_dt mit einem neuen Zeitstempel zu behandeln.

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

Der Trigger kann beliebig sein. Ich mag nur die Namenskonvention [trig] _ [my_table_name] _ [insert]


Ich wollte sagen: Wenn Sie Datensätze über den MySQL-Abfragebrowser manuell über das Raster ohne eine insert () -Anweisung einfügen, wird der Trigger benötigt. Wenn Sie immer eine insert-Anweisung verwenden, ist der Trigger völlig unnötig.

Hoppla! Ich meinte, der Auslöser (Name) kann so sein, wie Sie es möchten, da der Name des Auslösers die Funktionalität überhaupt nicht beeinflusst. Die meisten Leute werden das wissen, aber einige Leute, die neu in MySQL sind, wissen es vielleicht nicht ...

Huch, tut mir leid wegen des Mangels an Zeilenumbrüchen. Verwenden Sie die Semikolons, um das Ende jeder Zeile zu markieren.

24

Sie können Trigger verwenden, um diese Art von Sachen zu machen.

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

Für alle, die den Mut verloren haben, einen Standardwert für DATETIME in MySQL festzulegen , weiß ich genau, wie Sie sich fühlen. Also hier ist:

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

Beachten Sie sorgfältig, dass ich keine einfachen Anführungszeichen / doppelten Anführungszeichen um die 0 hinzugefügt habe

Ich springe buchstäblich, nachdem ich dieses Problem gelöst habe: D.


8
Es wird keine aktuelle Zeit eingefügt. Es wird '0000-00-00 00:00:00' eingefügt.
Pit Digger

8
Ich habe nicht gesagt, dass es die aktuelle Zeit einstellt. Viele Leute haben versucht, einen Standardwert von Null festzulegen, aber es funktioniert einfach nicht. Wir müssen die Anführungszeichen streichen. Da dieser Befund viel Zeit und Frustration verursachte, dachte ich daran, ihn mit der Community zu teilen. Personen wie Sie sind dafür verantwortlich, dass Benutzer das Interesse verlieren, nützliche Informationen mit anderen Personen zu teilen. Ich sehe keinen Grund, eine -1 zu bekommen! Wie auch immer.
Augiwan

3
Das gleiche könnte mit DATETIME NOT NULL erreicht werden.
Brendan Byrd

Der Beispielbefehl sql enthält noch ein weiteres `-Zeichen, das ich nicht bearbeiten kann, da es sich nur um eine Ein-Zeichen-Bearbeitung handelt.
Quapka

Ihr Code hat bei mir nicht funktioniert, hier ist, was funktioniert hatALTER TABLE zones MODIFY created datetime NOT NULL DEFAULT 0;
Smith


14

Wenn Sie die Tabelle bereits erstellt haben, können Sie sie verwenden

So ändern Sie den Standardwert auf das aktuelle Datum und die Uhrzeit

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

So ändern Sie den Standardwert 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

Ich verwende MySql Server 5.7.11 und diesen Satz:

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

wird nicht funktionieren. Aber folgendes:

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

funktioniert einfach .

Als Nebenbemerkung wird es in den MySQL-Dokumenten erwähnt :

Der Typ DATE wird für Werte mit einem Datumsteil, aber keinem Zeitteil verwendet. MySQL ruft DATE-Werte im Format 'JJJJ-MM-TT' ab und zeigt sie an. Der unterstützte Bereich ist '1000-01-01' bis '9999-12-31'.

auch wenn sie auch sagen:

Ungültige DATE-, DATETIME- oder TIMESTAMP-Werte werden in den Wert „Null“ des entsprechenden Typs ('0000-00-00' oder '0000-00-00 00:00:00') konvertiert.


8

Sie können now () verwenden, um den Wert einer datetime-Spalte festzulegen. Beachten Sie jedoch, dass Sie diesen Wert nicht als Standardwert verwenden können.


4
wahr. Ich habe gerade versucht, es jetzt zu verwenden, und habe die Fehlermeldung "Fehlercode: 1067. Ungültiger Standardwert" erhalten. Also, was ist die Antwort? ;-)
Brian Boatright

Dies ist die beste Lösung, um die MySQL-Versionen 5.5 und 5.6 zu kompromittieren. Legen Sie für Version 5.5 den Wert von fest NOW()und verwenden Sie ihn später für das Einfügen. Für Version 5.6 einfach NOW()als Standardwert festlegen .
Abel Callejo

8

Für alle, die die TIMESTAMP-Spalte als Lösung verwenden, möchte ich die folgende Einschränkung aus dem Handbuch unterstützen:

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

"Der TIMESTAMP-Datentyp hat einen Bereich von '1970-01-01 00:00:01' UTC bis ' 2038-01-19 03:14:07 ' UTC. Er hat je nach MySQL-Version und SQL unterschiedliche Eigenschaften Modus, in dem der Server ausgeführt wird. Diese Eigenschaften werden später in diesem Abschnitt beschrieben. "

Dies wird Ihre Software offensichtlich in etwa 28 Jahren beschädigen.

Ich glaube, die einzige Lösung auf der Datenbankseite besteht darin, Trigger zu verwenden, wie in anderen Antworten erwähnt.


2
Was wäre, wenn MySQL in 20 Jahren aktualisiert und diese Einschränkung aufgehoben würde? Ich bin mir nicht sicher, ob das möglich ist, sondern nur ein Gedanke.
NessDan

7

Beim Definieren mehrzeiliger Trigger muss das Trennzeichen geändert werden, da das Semikolon vom MySQL-Compiler als Ende des Triggers verwendet wird und Fehler generiert. z.B

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

5

So geht's unter MySQL 5.1:

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

Ich habe keine Ahnung, warum Sie den Spaltennamen zweimal eingeben müssen.


5
ÄNDERN dient auch zum Umbenennen des Feldes. Der erste Spaltenname ist der 'alte', der zweite Spaltenname ist der 'neue'. Es sieht überflüssig aus, wenn Sie den Namen des Feldes nicht ändern. Wenn es zu ästhetisch unangenehm ist, versuchen Sie es mit MODIFY.
John Gordon

5

Während Sie dies DATETIMEin der Standarddefinition nicht tun können , können Sie einfach eine select-Anweisung wie folgt in Ihre insert-Anweisung einfügen:

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

Beachten Sie das Fehlen von Anführungszeichen um die Tabelle.

Für MySQL 5.5


3

Wenn Sie versuchen, den Standardwert als NOW () festzulegen, unterstützt MySQL dies meiner Meinung nach nicht. In MySQL können Sie für keinen Spaltentyp eine Funktion oder einen Ausdruck als Standardwert verwenden, mit Ausnahme der Datentypspalte TIMESTAMP, für die Sie CURRENT_TIMESTAMP als Standard angeben können.


3

Ich denke, es ist einfach in MySQL, da MySQL die eingebaute Funktion now () heißt, die die aktuelle Zeit (Zeit dieser Einfügung) angibt.

Ihre Anfrage sollte also ähnlich aussehen

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

Vielen Dank.


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

In der obigen Abfrage zum Erstellen von 'testtable' habe ich '1999-12-12 12:12:12' als Standardwert für die DATETIME-Spalte verwendet colname


1

Verwenden Sie den folgenden Code

DELIMITER $$

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

    DELIMITER ;

0

Wenn Sie versuchen, den Standardwert als NOW () festzulegen, unterstützt MySQL, dass Sie den Typ dieser Spalte TIMESTAMP anstelle von DATETIME ändern müssen. TIMESTAMP haben standardmäßig das aktuelle Datum und die aktuelle Uhrzeit. Ich denke, es wird Ihr Problem lösen.


0

Nehmen wir zum Beispiel, wenn ich eine Tabelle mit dem Namen 'site' mit einer Spalte "created_at" und einer Spalte "update_at" hätte, die beide DATETIME waren und den Standardwert von now benötigen, könnte ich die folgende SQL ausführen, um dies zu erreichen.

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` aktualisierte_at`` aktualisierte_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;

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

Die Reihenfolge der Anweisungen ist wichtig, da eine Tabelle nicht zwei Spalten vom Typ TIMESTAMP mit den Standardwerten von CUREENT TIMESTAMP enthalten kann


0

Dies ist mein Trigger-Beispiel:

/************ 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

Funktioniert gut mit 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

Sie können den Standardzeitstempel auflösen. Überlegen Sie zunächst, welchen Zeichensatz Sie verwenden, wenn Sie beispielsweise utf8 verwendet haben, unterstützt dieser Zeichensatz alle Sprachen, und wenn Sie laten1 verwendet haben, unterstützt dieser Zeichensatz nur Englisch. Nächster Satz Wenn Sie unter einem Projekt arbeiten, sollten Sie die Client-Zeitzone kennen und auswählen, dass Sie Client-Zone sind. Dieser Schritt ist obligatorisch.


2
DateTime-Spalten dürfen keine Standardwerte haben. Es ist "Feature" dokumentiert. Nicht alle Entwickler haben Zugriff darauf, ihre Zeichenkodierung zu ändern. Und den Server darauf einstellen Zeitzone Client ist normalerweise nicht möglich, insbesondere wenn die Clients nicht alle in einem einzelnen Zeitzonenbereich nativ sind.
rlb.usa
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.