MySQL Tarih / Saat sütunu için varsayılan değeri nasıl ayarlarsınız?


898

MySQL Tarih / Saat sütunu için varsayılan değeri nasıl ayarlarsınız?

SQL Server'da öyle getdate(). MySQL için eşdeğer nedir? Bu bir faktör ise MySQL 5.x kullanıyorum.


4
Mysql tablomda (sorguda değil) CURRENT_TIMESTAMP kullanıyorum, belki de bu çok yararlı olabilir.
Ruben

15
Bu özellik MySQL 5.6.5 sürümüne eklendi. Umarım bu birine yardımcı olur. optimize-this.blogspot.co.uk/2012/04/…
GhostInTheSecureShell

@GhostInTheSecureShell, en azından Debian'a yüklemek için oldukça misyonu var, ama kesinlikle harika bir özellik. Sonunda tüm bu "iki CURRENT_TIMESTAMP" sorununun hafifletileceğini düşünüyorum!
Marc DiMillo

Şimdi () işlevidir, yoksa sütun düzeyinde varsayılan ayarlarla yapabilirsiniz.
Anshul Sharma

Yanıtlar:


862

ÖNEMLİ DÜZENLEME: MySQL 5.6.5'ten bu yana DATETIME alanları ile bunu başarmak mümkün , diğer gönderiye bir göz atın aşağıdaki ...

Önceki sürümler DATETIME ile yapamaz ...

Ama bunu TIMESTAMP ile yapabilirsiniz:

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: Varsayılan olarak CURRENT_TIMESTAMP ON olan bir sütun tanımlarsanız, DAİMA bu sütun için bir değer belirtmeniz gerekir veya değer güncelleme sırasında kendini otomatik olarak "now ()" olarak sıfırlar. Bu, değerin değişmesini istemiyorsanız, UPDATE ifadenizin "[sütun adınız] = [sütun adınız]" (veya başka bir değer) içermesi gerektiği veya değerin "now ()" olacağı anlamına gelir. Tuhaf, ama gerçek. Umarım bu yardımcı olur. 5.5.56-MariaDB ** kullanıyorum


400
tarih saatinin 1000-9999 aralığında olduğunu, ancak zaman damgası aralığının sadece 1970-2038 olduğunu belirtmek önemlidir . sisteminizin doğum tarihlerini saklaması veya 30 yıllık ipotek için ödeme planı gibi bir şeyle uğraşmanız gerekiyorsa bu bir sorun olabilir. dev.mysql.com/doc/refman/5.0/en/datetime.html
Kip

13
Sihirli bir şekilde otomatik olarak güncellendiğinden zaman damgasına da dikkat edin ... bir sonraki cevaba bakın stackoverflow.com/a/1483959/233906
Cerber

6
İse sürümü 5.6.5 dan aşağıya Gustav'ın cevaba bakınız mümkün (ben MySQL hala 5.0 iken Cevabınız gönderilmiş fark!)
e2-e4

4
@Kip, Merhaba, bir DATEsütun için varsayılan bir değere sahip olmak mümkün mü? ( datetimesütun değil ).
Sajib Acharya

ti DATE sütunları için mümkün görünmüyor: DATETIME veri türünü kullanmanız gerekiyor
Fabio Napodano

599

5.6.5 sürümünde, datetime sütununda varsayılan bir değer ayarlamak ve hatta satır güncellendiğinde güncellenecek bir sütun oluşturmak mümkündür. Tür tanımı:

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

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


3
'Menu_creation_time' için geçersiz varsayılan değer
Fernando Trindade

2
@FernandoTrindade MySQL sürüm 5.6.5 veya daha yenisine ihtiyacınız var. Burada çalıştığını görebilirsiniz: sqlfiddle.com/#!9/dd2be
Gustav Bertram

1
@GustavBertram, sürüm 5.6.22 kullanıyorum, ancak yine de aşağıdaki gibi hata var: CREATE TABLE tbl (InsertDate DATETIME NULL DEFAULT CURRENT_TIMESTAMP, UpdateDate TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP (6); Hata Kodu: 1294. 'UpdateDate' sütunu için geçersiz ON UPDATE deyimi
Manish Sapkal

@ManishSapkal DATETIME değil TIMESTAMP kullanıyorsunuz. Ayrıca, boş yapmayın.
Gustav Bertram

1
"ON UPDATE" sözdiziminin yanlış olduğunu düşünüyorum. Dev.mysql.com/doc/refman/5.6/tr/timestamp-initialization.html göre olmalıdırdt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Dan Bough

148

MySQL ( sürüm 5.6.5'ten önce ), varsayılan DateTime değerleri için işlevlerin kullanılmasına izin vermez. TIMESTAMP tuhaf davranışı nedeniyle uygun değildir ve giriş verisi olarak kullanılması önerilmez. (Bkz. MySQL Veri Türü Varsayılanları .)

Bununla birlikte, bir Tetikleyici oluşturarak bunu başarabilirsiniz .

DateTime türü bir DateCreated alanı olan bir tablo var. Bu tablo üzerinde "Insert Insert" ve " SET NEW.DateCreated=NOW()" üzerinde bir tetikleyici oluşturdum ve harika çalışıyor.

Umarım bu birine yardımcı olur.


21
TRIGGER OLUŞTUR Tetik_foo_SetCreatedAt HER ROW SET İÇİN foo'ya EKLEMEDEN ÖNCE NEW.created_at = UTC_TIMESTAMP ();
kgriffs

5
Muhtemelen bir zaman damgası kullanmak, gelecekteki akıl sağlığınız (bakım) için bir tetikleyiciden daha iyidir. Bu, bir çözüm olmasına rağmen, bir tetikleyici için çok önemli bir kullanım örneğidir.
getWeberForStackExchange

8
Muhtemelen sadece varsayılan değeri ayarlamak isteyeceksinizIF NEW.created_at IS NOT NULL
Petr Peller

132

Benim için tetikleyici yaklaşım en iyi sonucu verdi, ama yaklaşımla ilgili bir engel buldum. Eklemedeki geçerli saate bir tarih alanı ayarlamak için temel tetikleyiciyi düşünün:

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

Bu genellikle harika, ancak alanı INSERT ifadesi aracılığıyla manuel olarak ayarlamak istediğinizi varsayalım:

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

Olan şey, tetikleyicinin alan için sağladığınız değerin hemen üzerine yazmasıdır ve bu nedenle güncel olmayan bir zamanı ayarlamanın tek yolu bir takip UPDATE ifadesi - yuck! Bir değer sağlandığında bu davranışı geçersiz kılmak için, bu biraz değiştirilmiş tetikleyiciyi IFNULL işleci ile deneyin:

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

Bu, her iki dünyanın da en iyisini verir: Tarih sütununuz için bir değer sağlayabilirsiniz ve alır ve aksi takdirde varsayılan olarak geçerli saate göre ayarlanır. Hala tablo tanımında VARSAYILAN GETDATE () gibi temiz bir şeye göre getto, ama biz yaklaşıyoruz!


5
Ekteki açık kullanıcı değerlerinin üzerine yazılmasıyla uyarıyı onaylamak için +1.
Kip

2
Şahsen bunun en iyi yol olduğunu düşünüyorum. TIMESTAMP gerçekten garip bir davranış var ve ben asla 2038 yıl sınırlaması olan bir kod yazmak.
Eric

Boş ver, anladım. İzin verilecek alanı ayarlamayı unuttum NULL. Artık uyarı yok.
Kaji

Tetikleyiciler kötüdür! Onları sadece bir şey yapmanın başka bir yolu olmadığında kullanın. Bir tetikleyici kullanmaktansa 5.6.x kimliğine yükseltmek daha iyidir.
ksymeon

4
MySQL 5.5'te IFNULL, DATETIME üzerinde çalışmaz; yukarıdaki tetiği kullanarak dateAddedtüm '0000-00-00 00:00:00' gösterilir. Bunu kullanmak hile yapar: `NEW.date Added = 0 EĞER HER SATIR İÇİN SONRA NEW.date Added = NOW (); END IF; ``
Kenney

28

İki datetime alanı olan masamda bu alter deyimini kullanarak bunu çözebildim.

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;

Bu, now () işlevinin çalışmasını beklediğiniz gibi çalışır. Null değerlerinin eklenmesi veya created_dt ve updated_dt alanlarının yoksayılması, her iki alanda da mükemmel bir zaman damgası değeriyle sonuçlanır. Satırdaki herhangi bir güncelleme updated_dt dosyasını değiştirir. MySQL sorgu tarayıcısı aracılığıyla kayıt eklerseniz, bir adım daha gerekiyordu: trigger_dt dosyasını yeni bir zaman damgasıyla işlemek için bir tetikleyici.

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

Tetikleyici istediğiniz gibi olabilir Sadece adlandırma kuralını seviyorum [trig] _ [my_table_name] _ [insert]


Ben demek istiyorum ki, bir insert () deyimi olmadan ızgara üzerinden elle MySQL sorgu tarayıcısı aracılığıyla kayıtları eklerseniz, tetikleyici gereklidir. Her zaman bir insert deyimi kullanırsanız, tetik tamamen gereksizdir.

Tüh! Demek istediğim, tetikleyici (isim) olmasını istediğiniz her şey olabilir çünkü tetikleyici adı işlevselliği hiç etkilemez. Çoğu insan bunu bilecek, ancak MySQL için yeni olan bazı insanlar bilmiyor olabilir ...

Evet, satır sonları olmadığı için üzgünüm. Her satırın sonunu işaretlemek için noktalı virgül kullanın.

24

Bu tür şeyler yapmak için tetikleyicileri kullanabilirsiniz.

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

Varsayılan bir ayarlamaya çalışırken kalbi kaybeden herkes için DATETIME değeri MySQL sen / keçeyi nasıl hissettiğini, kesinlikle biliyorum. İşte burada:

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

Dikkatle gözlemleyin ben tek tırnak / çift tırnak eklememiş etrafında 0

Bunu çözdükten sonra tam anlamıyla zıplıyorum: D


8
Geçerli saati değil. '0000-00-00 00:00:00' ekleyecektir.
Pit Digger

8
Şu anki saati ayarladığını söylemedim. Birçok kişi varsayılan sıfır değeri ayarlamaya çalışıyorlardı, ama işe yaramıyor. Alıntıları ortadan kaldırmamız gerekiyor. Bu bulgu çok zaman ve hayal kırıklığına neden olduğu için, bunu toplulukla paylaşmayı düşündüm. Sizin gibi kişiler, başkalarıyla yararlı bilgiler paylaşmaktan ilgi duyan kullanıcılardan sorumludur. -1 almak için ciddi bir neden görmüyorum! Her neyse.
Augiwan

3
Aynı şey DATETIME NOT NULL ile elde edilebilir.
Brendan Byrd

Örnek sql komutunun içinde yalnızca bir karakterli düzenleme olduğu için düzenleyemediğim bir `` karakteri daha var.
quapka

kodunuz benim için çalışmadı, işte buradaALTER TABLE zones MODIFY created datetime NOT NULL DEFAULT 0;
Smith


14

Tabloyu daha önce oluşturduysanız,

Varsayılan değeri geçerli tarih saatiyle değiştirmek için

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

Varsayılan değeri '2015-05-11 13:01:01' olarak değiştirmek için

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


9

MySql Server 5.7.11 çalıştırıyorum ve bu cümle:

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

edilir değil çalışma. Ancak aşağıdakiler:

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

sadece çalışır .

Bir sidenote olarak , mysql belgelerinde belirtilmiştir :

DATE türü, tarih bölümü olan ancak saat bölümü olmayan değerler için kullanılır. MySQL, DATE değerlerini 'YYYY-AA-GG' biçiminde alır ve görüntüler. Desteklenen aralık '1000-01-01' ila '9999-12-31'dir.

ayrıca şunu da söyleseler bile:

Geçersiz DATE, DATETIME veya TIMESTAMP değerleri uygun türdeki “sıfır” değerine dönüştürülür ('0000-00-00' veya '0000-00-00 00:00:00').


8

Tarih (saat) sütununun değerini ayarlamak için now () öğesini kullanabilirsiniz, ancak bunu varsayılan değer olarak kullanamayacağınızı unutmayın.


4
doğru. Şimdi kullanmayı denedim ve "Hata Kodu: 1067. Geçersiz varsayılan değer" hatası aldım. peki cevap ne? ;-)
Brian Boatright

Bu, MySQL 5.5 ve 5.6 sürümlerinden ödün vermek için en iyi çözümdür. Sürüm 5.5 için değerini önceden belirleyin NOW()ve daha sonra ekleme için kullanın. 5.6 sürümü NOW()için varsayılan değer olarak ayarlamanız yeterlidir .
Abel Callejo

8

TIMESTAMP sütununu bir çözüm olarak kullanan herkes için, el kitabından aşağıdaki sınırlamayı ikna etmek istiyorum:

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

"TIMESTAMP veri türünün aralığı ' 1970-01-01 00:00:01' UTC'den ' 2038-01-19 03:14:07 . MySQL sürümüne ve SQL'e bağlı olarak değişen özelliklere sahiptir. sunucunun çalıştığı modda. Bu özellikler bu bölümün ilerleyen kısımlarında açıklanmaktadır. "

Yani bu yazılımınızı yaklaşık 28 yıl içinde bozacaktır.

Veritabanı tarafında tek çözüm diğer cevaplarda belirtildiği gibi tetikleyicileri kullanmak olduğuna inanıyorum.


2
MySQL 20 yıl sonra güncellenirse ve bu sınırlama kaldırılırsa ne olur? Bunun mümkün olup olmadığından emin değilim, sadece bir düşünce.
NessDan

7

Çok satırlı tetikleyicileri tanımlarken, noktalı virgülün değiştirilmesi gerekir, çünkü noktalı virgül MySQL derleyicisi tarafından tetiklemenin sonu olarak alınır ve hata üretir. Örneğin

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

5

MySQL 5.1'de nasıl yapılacağı aşağıda açıklanmıştır:

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

Neden sütun adını iki kez girmeniz gerektiğine dair hiçbir fikrim yok.


5
CHANGE ayrıca alanı yeniden adlandırmak içindir. İlk sütun adı 'eski', ikinci sütun adı 'yeni'. Alanın adını değiştirmiyorsanız gereksiz görünüyor. Çok estetik açıdan hoşnutsuzsa, DEĞİŞTİR'i deneyin.
John Gordon

5

Bunu DATETIMEvarsayılan tanımda yapamasanız da, insert deyiminize böyle bir select deyimini dahil edebilirsiniz:

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

Tablo etrafında tırnak eksikliği dikkat edin.

MySQL 5.5 için


3

Varsayılan değeri NOW () olarak ayarlamaya çalışıyorsanız, MySQL'in bunu desteklediğini sanmıyorum. MySQL'de, CURRENT_TIMESTAMP değerini varsayılan olarak belirtebileceğiniz TIMESTAMP veri türü sütunu dışında herhangi bir sütun türü için varsayılan değer olarak bir işlev veya ifade kullanamazsınız.


3

Ben mysql beri mysql şimdiki zaman (o insert zaman) veren now () denilen dahili işlevi basit olduğunu düşünüyorum.

Bu yüzden sorgunuz benzer şekilde görünmelidir

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

Teşekkür ederim.


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

Yukarıdaki sorguda 'testtable' oluşturmak için, '1999-12-12 12:12:12' değerini DATETIME sütunu için varsayılan değer olarak kullandım colname


1

Aşağıdaki kodu kullanın

DELIMITER $$

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

    DELIMITER ;

0

Varsayılan değeri NOW () olarak ayarlamaya çalışıyorsanız, MySQL, DATETIME yerine TIMESTAMP sütununun türünü değiştirmeniz gerektiğini destekler. TIMESTAMP varsayılan olarak geçerli tarih ve saate sahiptir .. bence sorununuzu çözecektir ..


0

Örneğin, DATETIME olan ve şu an için varsayılan değere ihtiyaç duyulan bir create_at ve update_at sütununa sahip 'site' adlı bir tablom olsaydı, bunu başarmak için aşağıdaki sql'i yürütebilirim.

ALTER TABLE `site` CHANGE` created_at`` created_at` TIMESTAMP BOŞ DEĞİL DEFAULT CURRENT_TIMESTAMP;

ALTER TABLE `site` CHANGE` yaratılmış_at`` oluşturulur_at` DATETIME NULL VARSAYILAN NULL;

ALTER TABLE `site` CHANGE` updated_at`` updated_at` TIMESTAMP BOŞ DEĞİL DEFAULT CURRENT_TIMESTAMP;

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

Bir tablonun varsayılan değerleri CUREENT TIMESTAMP olan TIMESTAMP türünde iki sütun bulunamadığından, ifade sırası önemlidir


0

Bu benim tetik örneğim:

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

MySQL 8.x ile iyi çalışıyor

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

Varsayılan zaman damgasını çözebilirsiniz. Öncelikle hangi karakter setini kullandığınızı düşünün; örneğin, utf8'i aldıysanız bu karakter seti tüm dilleri destekliyorsa ve u laten1 aldıysanız, bu karakter seti sadece İngilizce'yi desteklemektedir. Sonraki setp herhangi bir proje altında çalışıyorsanız, istemci saat dilimini bilmeli ve istemci bölge olduğunuzu seçmelisiniz. Bu adım zorunludur.


2
DateTime sütunlarında varsayılan değerler olamaz. 'Özellik' belgelenmiştir. Tüm geliştiricilerin karakter kodlamalarını değiştirme erişimi yoktur. Sunucuyu istemcilerin saat dilimine ayarlamak , özellikle istemcilerin tümü tek bir saat dilimi alanına özgü olmadığında, genellikle bir olasılık değildir.
rlb.usa
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.