Jak ustawić wartość domyślną dla kolumny MySQL Datetime?

898

Jak ustawić wartość domyślną dla kolumny MySQL Datetime?

W SQL Server to jest getdate(). Jaki jest odpowiednik MySQL? Używam MySQL 5.x, jeśli to jest czynnik.

Brian Boatright
źródło
4
Używam CURRENT_TIMESTAMP w mojej tabeli mysql (nie w zapytaniu), może to też może być pomocne.
Ruben
15
Ta funkcja została teraz dodana do MySQL 5.6.5. Mam nadzieję, że to komuś pomoże. optimize-this.blogspot.co.uk/2012/04/…
GhostInTheSecureShell
@GhostInTheSecureShell to misja instalacji, przynajmniej na Debianie, ale zdecydowanie niesamowita funkcja. Myślę, że w końcu wszystkie te „dwa CURRENT_TIMESTAMP” zostaną złagodzone!
Marc DiMillo,
jest to teraz () funkcja lub możesz to zrobić przy ustawieniach domyślnych na poziomie kolumny.
Anshul Sharma

Odpowiedzi:

862

WAŻNA EDYCJA: Teraz można to osiągnąć za pomocą pól DATETIME od MySQL 5.6.5 , spójrz na inny post poniżej ...

Poprzednie wersje nie mogły tego zrobić z DATETIME ...

Ale możesz to zrobić za pomocą 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: JEŚLI zdefiniujesz kolumnę z CURRENT_TIMESTAMP ON jako domyślną, ZAWSZE musisz podać wartość dla tej kolumny lub wartość automatycznie zresetuje się do „teraz ()” podczas aktualizacji. Oznacza to, że jeśli nie chcesz, aby wartość się zmieniała, twoja instrukcja UPDATE musi zawierać „[twoja nazwa kolumny] = [twoja nazwa kolumny]” (lub jakąś inną wartość), inaczej wartość zmieni się w „teraz ()”. Dziwne, ale prawdziwe. Mam nadzieję, że to pomoże. Używam 5.5.56-MariaDB **

sebthebert
źródło
400
należy zauważyć, że datetime ma zakres 1000–9999, ale zakres datownika wynosi tylko 1970–2038 . może to stanowić problem, jeśli Twój system musi przechowywać daty urodzenia lub musisz obsługiwać coś takiego, jak plan spłaty kredytu hipotecznego na 30 lat. dev.mysql.com/doc/refman/5.0/en/datetime.html
Kip
13
Bądź również ostrożny ze znacznikiem czasu, ponieważ automatycznie aktualizuje się magicznie ... zobacz następną odpowiedź stackoverflow.com/a/1483959/233906
Cerber
6
Jest to możliwe od wersji 5.6.5, patrz odpowiedź Gustava poniżej (zdaję sobie sprawę, że twoja odpowiedź została opublikowana, gdy MySQL był jeszcze 5.0!)
e2-e4
4
@Kip, Cześć, czy można mieć domyślną wartość dla DATEkolumny? (nie datetimekolumna).
Sajib Acharya
Wydaje się, że ti nie jest możliwe dla kolumn DATE: musisz użyć typu danych DATETIME
Fabio Napodano
598

W wersji 5.6.5 możliwe jest ustawienie wartości domyślnej w kolumnie daty i godziny, a nawet utworzenie kolumny, która będzie aktualizowana po aktualizacji wiersza. Definicja typu:

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

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

Gustav Bertram
źródło
3
Nieprawidłowa wartość domyślna „menu_creation_time”
Fernando Trindade,
2
@FernandoTrindade Potrzebujesz MySQL w wersji 5.6.5 lub nowszej. Możesz zobaczyć, jak działa tutaj: sqlfiddle.com/#!9/dd2be
Gustav Bertram
1
@GustavBertram, używam wersji 5.6.22, ale nadal pojawia się błąd: CREATE TABLE tbl (InsertDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, UpdateDate TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP (6)); Kod błędu: 1294. Niepoprawna klauzula ON UPDATE dla kolumny „UpdateDate”
Manish Sapkal
@ManishSapkal Używasz TIMESTAMPA, a nie DATETIME. Nie rób też NULL.
Gustav Bertram,
1
Myślę, że składnia „ON UPDATE” jest nieprawidłowa. Według dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html powinno byćdt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Dan Bough
148

MySQL ( przed wersją 5.6.5 ) nie pozwala na używanie funkcji dla domyślnych wartości DateTime. TIMESTAMP nie jest odpowiedni ze względu na swoje dziwne zachowanie i nie jest zalecany do stosowania jako danych wejściowych. (Zobacz Domyślne typy danych MySQL .)

To powiedziawszy, możesz to zrobić , tworząc Trigger .

Mam tabelę z polem DateCreated typu DateTime. Utworzyłem wyzwalacz na tym stole „Przed wstawieniem” i „ SET NEW.DateCreated=NOW()” i działa świetnie.

Mam nadzieję, że to komuś pomoże.

Stephan Unrau
źródło
21
UTWÓRZ WYZWALACZ trigger_foo_SetCreatedAT PRZED WPROWADZENIEM Foo DLA KAŻDEGO ZESTAWU WIERSZY NEW.created_at = UTC_TIMESTAMP ();
kgriffs
5
Prawdopodobnie lepiej będzie użyć sygnatury czasowej niż wyzwalacza przyszłego zdrowia psychicznego (konserwacja). Jest to zbyt trywialny przypadek użycia wyzwalacza, chociaż jest to rozwiązanie.
getWeberForStackExchange
8
Prawdopodobnie będziesz chciał ustawić tylko wartość domyślnąIF NEW.created_at IS NOT NULL
Petr Peller
132

Dla mnie podejście wyzwalające działało najlepiej, ale znalazłem problem z podejściem. Rozważ podstawowy wyzwalacz, aby ustawić pole daty na bieżącą godzinę przy wstawianiu:

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

Jest to zwykle świetne, ale powiedz, że chcesz ustawić pole ręcznie za pomocą instrukcji INSERT, na przykład:

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

To, co się dzieje, polega na tym, że wyzwalacz natychmiast zastępuje podaną wartość dla pola, a zatem jedynym sposobem na ustawienie czasu nieaktualnego jest następująca instrukcja UPDATE - fuj! Aby zastąpić to zachowanie po podaniu wartości, wypróbuj ten nieco zmodyfikowany wyzwalacz z operatorem IFNULL:

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

To daje to, co najlepsze z obu światów: możesz podać wartość dla swojej kolumny daty, która zajmie, w przeciwnym razie domyślnie przyjmie bieżącą godzinę. To wciąż getto w stosunku do czegoś czystego, takiego jak DEFAULT GETDATE () w definicji tabeli, ale zbliżamy się!

John Larson
źródło
5
+1 za potwierdzenie zastrzeżenia z zastąpieniem jawnych wartości użytkownika na wstawce.
Kip
2
Osobiście uważam, że to najlepsza droga. TIMESTAMP rzeczywiście ma dziwne zachowanie i nigdy nie napisałbym kodu, który ma ograniczenie do 2038 roku.
Eric
Nieważne, rozgryzłem to. Zapomniałem ustawić pole zezwalające NULL. Żadnych ostrzeżeń.
Kaji
Wyzwalacze są złe! Używaj ich tylko wtedy, gdy nie ma innego sposobu na zrobienie czegoś. Lepiej zaktualizować do wersji 5.6.x id, niż możesz użyć wyzwalacza.
ksymeon
4
W MySQL 5.5 IFNULL nie działa w DATETIME; użycie powyższego wyzwalacza dateAddedspowoduje wyświetlenie wszystkich „0000-00-00 00:00:00”. Korzystanie z tego robi sztuczkę: `DLA KAŻDEJ WIERSZY JEŚLI NEW.dateAdded = 0 TO NASTĘPNIE NEW.dateAdded = NOW (); KONIEC JEŻELI; `
Kenney,
28

Udało mi się to rozwiązać za pomocą tej instrukcji alter w mojej tabeli, która miała dwa pola daty i godziny.

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;

Działa to tak, jak można oczekiwać od funkcji now (). Wstawienie wartości null lub zignorowanie pól create_dt i updated_dt daje idealną wartość znacznika czasu w obu polach. Każda aktualizacja wiersza zmienia wartość updated_dt. Jeśli wstawisz rekordy za pomocą przeglądarki zapytań MySQL, potrzebujesz jeszcze jednego kroku, wyzwalacza do obsługi utworzonego_dt z nowym znacznikiem czasu.

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

Wyzwalaczem może być cokolwiek chcesz. Po prostu podoba mi się konwencja nazewnictwa [trig] _ [moja_tabela_nazwa] _ [wstaw]

188217
źródło
Chciałem powiedzieć, że jeśli wstawisz rekordy ręcznie za pomocą przeglądarki zapytań MySQL za pomocą siatki bez instrukcji insert (), wyzwalacz jest potrzebny. Jeśli zawsze używasz instrukcji insert, wyzwalacz jest całkowicie niepotrzebny.
Ups! Miałem na myśli, że wyzwalaczem (nazwą) może być dowolna nazwa, ponieważ nazwa wyzwalacza w ogóle nie wpływa na funkcjonalność. Większość ludzi to wie, ale niektórzy nowi użytkownicy MySQL mogą nie wiedzieć ...
Yikes, przepraszam za brak przerw w linii. Użyj średników, aby zaznaczyć koniec każdej linii.
24

Możesz użyć wyzwalaczy do zrobienia tego typu rzeczy.

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
źródło
18

Dla wszystkich, którzy stracili serce, próbując ustawić domyślną wartość DATETIME w MySQL , wiem dokładnie, jak się czujesz / czujesz. Oto więc:

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

Uważnie obserwuj, że nie dodałem pojedynczych cudzysłowów / podwójnych cudzysłowów wokół zera

Skaczę dosłownie po rozwiązaniu tego: D

Augiwan
źródło
8
Nie wstawia nie aktualnego czasu. Wstawi „0000-00-00 00:00:00”.
Pit Digger
8
Nie powiedziałem, że ustawia aktualny czas. Wiele ppl próbowało / próbuje ustawić domyślną wartość zerową, ale to po prostu nie działa. Musimy wyeliminować cytaty. Ponieważ odkrycie to spowodowało wiele czasu i frustracji, pomyślałem o udostępnieniu go społeczności. Osoby takie jak ty są odpowiedzialne za to, że użytkownicy tracą zainteresowanie udostępnianiem przydatnych informacji innym osobom. Naprawdę nie widzę żadnego powodu, aby uzyskać -1! Cokolwiek.
Augiwan
3
To samo można osiągnąć dzięki DATETIME NOT NULL.
Brendan Byrd
W przykładowej komendzie sql znajduje się jeszcze jeden znak, którego nie mogę edytować, ponieważ jest to edycja jednoznakowa.
quapka
twój kod nie działał dla mnie, oto co zadziałałoALTER TABLE zones MODIFY created datetime NOT NULL DEFAULT 0;
Smith
14

Jeśli już utworzyłeś tabelę, możesz jej użyć

Aby zmienić wartość domyślną na bieżącą datę i godzinę

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

Aby zmienić wartość domyślną na „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
źródło
9

Używam MySql Server 5.7.11 i tego zdania:

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

to nie działa. Ale następujące:

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

po prostu działa .

Jako sidenote wspomina się w dokumentach mysql :

Typ DATA jest używany dla wartości z częścią daty, ale bez części godziny. MySQL pobiera i wyświetla wartości DATE w formacie „RRRR-MM-DD”. Obsługiwany zakres to „1000-01-01” do „9999-12-31”.

nawet jeśli mówią również:

Nieprawidłowe wartości DATE, DATETIME lub TIMESTAMP są konwertowane na wartość „zero” odpowiedniego typu („0000-00-00” lub „0000-00-00 00:00:00”).

Evhz
źródło
8

Możesz użyć now (), aby ustawić wartość kolumny datetime, ale pamiętaj, że nie możesz użyć tej wartości jako wartości domyślnej.

Jądro
źródło
4
prawdziwe. Właśnie próbowałem użyć teraz i otrzymałem błąd „Kod błędu: 1067. Niepoprawna wartość domyślna.”. więc jaka jest odpowiedź? ;-)
Brian Boatright
To najlepsze rozwiązanie dla kompromitacji MySQL w wersji 5.5 i 5.6. W przypadku wersji 5.5 wstępnie ustal wartość NOW()i użyj jej później do wstawienia. W wersji 5.6 po prostu ustaw NOW()jako wartość domyślną.
Abel Callejo,
8

Dla wszystkich, którzy używają kolumny TIMESTAMP jako rozwiązania, chcę poprzeć następujące ograniczenie z instrukcji:

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

„Typ danych TIMESTAMP ma zakres od„ 1970-01-01 00:00:01 ”UTC do„ 2038-01-19 03:14:07 ”UTC. Ma różne właściwości, w zależności od wersji MySQL i SQL tryb, w którym działa serwer. Te właściwości są opisane w dalszej części tej sekcji. ”

To oczywiście zepsuje twoje oprogramowanie za około 28 lat.

Uważam, że jedynym rozwiązaniem po stronie bazy danych jest użycie wyzwalaczy, jak wspomniano w innych odpowiedziach.

fabiański
źródło
2
Co jeśli MySQL został zaktualizowany za 20 lat i to ograniczenie zostało usunięte? Nie jestem pewien, czy to możliwe, ale tylko myśl.
NessDan
7

Podczas definiowania wyzwalaczy wieloliniowych należy zmienić separator, ponieważ średnik będzie brany przez kompilator MySQL jako koniec wyzwalacza i generuje błąd. na przykład

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
źródło
5

Oto jak to zrobić na MySQL 5.1:

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

Nie mam pojęcia, dlaczego musisz wpisać nazwę kolumny dwa razy.

Samuel
źródło
5
CHANGE służy również do zmiany nazwy pola. Nazwa pierwszej kolumny to „stara”, nazwa drugiej kolumny to „nowa”. Wygląda na zbędny, jeśli nie zmieniasz nazwy pola. Jeśli jest to zbyt nieprzyjemne pod względem estetycznym, wypróbuj MODYFIKUJ.
John Gordon,
5

Chociaż nie możesz tego zrobić DATETIMEw definicji domyślnej, możesz po prostu dołączyć instrukcję select do instrukcji insert w następujący sposób:

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

Zwróć uwagę na brak cytatów przy stole.

Dla MySQL 5.5

Jerzy
źródło
3

Jeśli próbujesz ustawić wartość domyślną jako NOW (), nie sądzę, że MySQL to obsługuje. W MySQL nie można używać funkcji ani wyrażenia jako wartości domyślnej dla dowolnego typu kolumny, z wyjątkiem kolumny typu danych TIMESTAMP, dla której można określić CURRENT_TIMESTAMP jako domyślną.

Vijesh VP
źródło
3

Myślę, że jest to proste w mysql, ponieważ mysql to wbudowana funkcja o nazwie now (), która podaje aktualny czas (czas wstawienia).

Twoje zapytanie powinno więc wyglądać podobnie

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

Dziękuję Ci.

Deepak N.
źródło
2
CREATE TABLE `testtable` (
    `id` INT(10) NULL DEFAULT NULL,
    `colname` DATETIME NULL DEFAULT '1999-12-12 12:12:12'
)

W powyższym zapytaniu do utworzenia „tabeli testowej” użyłem „1999-12-12 12:12:12” jako wartości domyślnej dla kolumny DATETIME colname

Fathah Rehman P.
źródło
1

Użyj następującego kodu

DELIMITER $$

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

    DELIMITER ;
Rana Aalamgeer
źródło
0

Jeśli próbujesz ustawić wartość domyślną jako NOW (), MySQL obsługuje, że musisz zmienić typ tej kolumny TIMESTAMP zamiast DATETIME. TIMESTAMP ma domyślnie bieżącą datę i godzinę. Myślę, że to rozwiąże problem ..

Dhrumil Shah
źródło
0

Weźmy na przykład, jeśli miałbym tabelę o nazwie „site” z kolumną create_at i kolumną update_at, które były zarówno DATETIME i potrzebują domyślnej wartości teraz, mógłbym wykonać następujący kod SQL, aby to osiągnąć.

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;

Kolejność instrukcji jest ważna, ponieważ tabela nie może mieć dwóch kolumn typu TIMESTAMP z domyślnymi wartościami CUREENT TIMESTAMP

Joseph Persie
źródło
0

To jest mój przykład wyzwalacza:

/************ 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
źródło
0

Działa poprawnie z 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
źródło
-3

Możesz rozwiązać domyślny znacznik czasu. Najpierw zastanów się, którego zestawu znaków używasz, na przykład jeśli użyłeś utf8, ten zestaw znaków obsługuje wszystkie języki, a jeśli wziąłeś laten1, ten zestaw znaków obsługuje tylko angielski. Następnie, jeśli pracujesz nad jakimkolwiek projektem, powinieneś znać strefę czasową klienta i wybrać strefę klienta. Ten krok jest obowiązkowy.

Srinivas
źródło
2
Kolumny DateTime nie mogą mieć wartości domyślnych. Jest to udokumentowana „funkcja”. Nie wszyscy programiści mają dostęp do zmiany kodowania znaków. A ustawienie serwera na strefę czasową klienta zwykle nie jest możliwe, szczególnie gdy klienci nie są natywni w jednym obszarze czasowym.
rlb.usa