MySQL 4.0'da hem Oluşturulan hem de Son Güncelleme zaman damgası sütunlarına sahip olmak


127

Aşağıdaki tablo şemasına sahibim;

CREATE TABLE `db1`.`sms_queue` (
  `Id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `Message` VARCHAR(160) NOT NULL DEFAULT 'Unknown Message Error',
  `CurrentState` VARCHAR(10) NOT NULL DEFAULT 'None',
  `Phone` VARCHAR(14) DEFAULT NULL,
  `Created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `LastUpdated` TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP,
  `TriesLeft` tinyint NOT NULL DEFAULT 3,
  PRIMARY KEY (`Id`)
)
ENGINE = InnoDB;

Aşağıdaki hatayla başarısız olur:

ERROR 1293 (HY000): Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause.

Sorum şu, bu alanların ikisine de sahip olabilir miyim? veya her işlem sırasında manuel olarak bir LastUpdated alanı ayarlamam gerekir mi?


Hey, @Xenph Yan, "Kabul Edildi" cevabını şu anki yanlış cevaptan doğru olana değiştirebilir misin? Bu kabul edilmiş, yanlış cevap, neler olduğunu anlamaya çalışırken yaklaşık 15 dakika kaybetmeme neden oldu ...
Bruno Reis

1
@BrunoReis Bitti, aldığınız için teşekkürler.
Xenph Yan

Yanıtlar:


128

Gönderen MySQL 5.5 belgelerinde :

Bir tablodaki bir TIMESTAMP sütunu, sütunu başlatmak için varsayılan değer olarak, otomatik güncelleme değeri olarak veya her ikisi olarak geçerli zaman damgasını içerebilir. Geçerli zaman damgasının bir sütun için varsayılan değer ve başka bir sütun için otomatik güncelleme değeri olması mümkün değildir.

MySQL 5.6.5'teki değişiklikler :

Önceden, tablo başına en fazla bir TIMESTAMP sütunu otomatik olarak başlatılabilir veya geçerli tarih ve saate göre güncellenebilirdi. Bu kısıtlama kaldırıldı. Herhangi bir TIMESTAMP sütun tanımı, DEFAULT CURRENT_TIMESTAMP ve ON UPDATE CURRENT_TIMESTAMP yan tümcelerinin herhangi bir kombinasyonuna sahip olabilir. Ek olarak, bu cümlecikler artık DATETIME sütun tanımlarıyla kullanılabilir. Daha fazla bilgi için, bkz. TIMESTAMP ve DATETIME için Otomatik Başlatma ve Güncelleme.


Bu değişti (en azından MySQL 5.0'da). Belgelere bakın: dev.mysql.com/doc/refman/5.0/en/timestamp.html
SimonSimCity

@SimonSimCity'ye karşı: 5.0 için dokümanlar, yukarıdakiyle aynı şeyi söylüyor.
davemyron

5
@RobertGamble Bence daha ilginç soru NEDEN HECK bu çok sık talep edilen / ihtiyaç duyulan işlevselliği yapmak için bir yol sağlamadılar.
Ray

22
Bu, MySQL açısından biraz keyfi görünüyor. Bunun neden böyle olduğunu kimse açıklayabilir mi?
humble_coder

12
Gerçekten çok eski bir yorum, AMA, sonunda değişti: Changes in MySQL 5.6.5 (2012-04-10, Milestone 8) Previously, at most one TIMESTAMP column per table could be automatically initialized or updated to the current date and time. This restriction has been lifted. Any TIMESTAMP column definition can have any combination of DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP clauses. In addition, these clauses now can be used with DATETIME column definitions. For more information, see Automatic Initialization and Updating for TIMESTAMP and DATETIME.
Mauricio Vargas

83

Her iki zaman damgasına da sahip olmanın bir numarası var, ancak biraz sınırlama var.

Bir tabloda tanımlardan yalnızca birini kullanabilirsiniz. Her iki zaman damgası sütununu şu şekilde oluşturun:

create table test_table( 
  id integer not null auto_increment primary key, 
  stamp_created timestamp default '0000-00-00 00:00:00', 
  stamp_updated timestamp default now() on update now() 
); 

Aşağıdaki durumlarda nullher iki sütuna da girmeniz gerektiğini unutmayın insert:

mysql> insert into test_table(stamp_created, stamp_updated) values(null, null); 
Query OK, 1 row affected (0.06 sec)

mysql> select * from test_table; 
+----+---------------------+---------------------+ 
| id | stamp_created       | stamp_updated       |
+----+---------------------+---------------------+
|  2 | 2009-04-30 09:44:35 | 2009-04-30 09:44:35 |
+----+---------------------+---------------------+
2 rows in set (0.00 sec)  

mysql> update test_table set id = 3 where id = 2; 
Query OK, 1 row affected (0.05 sec) Rows matched: 1  Changed: 1  Warnings: 0  

mysql> select * from test_table;
+----+---------------------+---------------------+
| id | stamp_created       | stamp_updated       | 
+----+---------------------+---------------------+ 
|  3 | 2009-04-30 09:44:35 | 2009-04-30 09:46:59 | 
+----+---------------------+---------------------+ 
2 rows in set (0.00 sec)  

İşte bu işlevi açıklayan MySQL Belgelerinden bir bağlantı: dev.mysql.com/doc/refman/5.0/en/timestamp.html
SimonSimCity

6
ilk kod kutusu, manuel olarak girildiğinde benim için mükemmel çalıştı. Teşekkürler! Pastırmamı kurtardığı için bu cevabı yükseltmek için yeterli 'karmam' olmasını dilerdim. mmmmm pastırma kurtardı.
amatusko

Bunun stamp_created da NULL DEĞİL olarak ayarlandığından emin olmalısınız . MySQL, NULL'u otomatik olarak geçerli zaman damgasıyla değiştirecektir.
Valentin Despa

Neden stamp_createdalanı stamp_created timestamp default now()'SIFIR' değeri kullanmak yerine şu şekilde yapmıyorsunuz ?
Sebastian Scholle

28

İkisine birden sahip olabilirsiniz, sadece oluşturulan alanda "CURRENT_TIMESTAMP" bayrağını kaldırmanız yeterlidir. Tabloda yeni bir kayıt oluşturduğunuzda, bir değer için "NOW ()" kullanın.

Veya.

Aksine, 'ON UPDATE CURRENT_TIMESTAMP' bayrağını kaldırın ve bu alan için ŞİMDİ () gönderin. Bu yol aslında daha mantıklı.


2
Tek yolu bu mu? Veritabanının tüm bu ayrıntılara bakmasını sağlayamaz mıyım?
Xenph Yan

2
MySql kılavuzuna göre, CURRENT_TIMESTAMP NOW () ile eşanlamlıdır, bu yüzden bunun işe yarayacağını düşünmüyorum.
tvanfosson

Eminim yapabilirsin, sadece CURRENT_TIMESTAMP sadece bir alan için ayrılmış bir bayraktır. Her iki durumda da, bir kayıt eklediğinizde o alan için hangi değere sahip olduğunuza bakılmaksızın, o bayrak her zaman geçerli zaman damgası, dolayısıyla ad olacaktır.
Stephen Walcher

1
@tvanfosson: Bir sorguda 'NOW ()' kullanılması geçerli zamanı veritabanına geçirir. Bu değerin gerçekte ne olduğu dile, motora ve muhtemelen bilmediğim diğer yüzlerce şeye bağlıdır. Bahsettiğim bayrak, onu bir kayıt oluşturulduğunda, o alana zaman eklenecek şekilde ayarlıyor.
Stephen Walcher

2
Ek ŞİMDİ () yöntemini kullandım, çoğunlukla diğer kodlar bu tablolara dokunabilir ve insanların bunları doğru şekilde güncelleyeceğine güvenmiyorum. :)
Xenph Yan

26

Zaman damgalarının güncellemesini MySQL'in yapmasına karar verirseniz, alanı eklemede güncellemek için bir tetikleyici ayarlayabilirsiniz.

CREATE TRIGGER <trigger_name> BEFORE INSERT ON <table_name> FOR EACH ROW SET NEW.<timestamp_field> = CURRENT_TIMESTAMP;

MySQL Referansı: http://dev.mysql.com/doc/refman/5.0/en/triggers.html


Güzel, aradığım buydu. Sorguya ŞİMDİ () eklenen kişilere güvenmek zorunda kalmak istemiyorum!
Bot

aslında bunu ekledikten sonra yapmak ve YENİ olarak ayarlamak daha iyi olurdu. <timestamp_field> = new. <timestamp_field aslında varsayılan current_timestamp'a sahip olmalı> bu şekilde her iki alan da
uyumludur

@KacieHouser Tetiklemeden sonra YENİ satırın güncellenmesine izin verilmiyor
Thomas

23

Tetikleyicileri kullanarak otomatik ve esnek createDate / lastModified alanlarına bu şekilde sahip olabilirsiniz:

Önce onları şu şekilde tanımlayın:

CREATE TABLE `entity` (
  `entityid` int(11) NOT NULL AUTO_INCREMENT,
  `createDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `lastModified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `name` varchar(255) DEFAULT NULL,
  `comment` text,
  PRIMARY KEY (`entityid`),
)

Ardından şu tetikleyicileri ekleyin:

DELIMITER ;;
CREATE trigger entityinsert BEFORE INSERT ON entity FOR EACH ROW BEGIN SET NEW.createDate=IF(ISNULL(NEW.createDate) OR NEW.createDate='0000-00-00 00:00:00', CURRENT_TIMESTAMP, IF(NEW.createDate<CURRENT_TIMESTAMP, NEW.createDate, CURRENT_TIMESTAMP));SET NEW.lastModified=NEW.createDate; END;;
DELIMITER ;
CREATE trigger entityupdate BEFORE UPDATE ON entity FOR EACH ROW SET NEW.lastModified=IF(NEW.lastModified<OLD.lastModified, OLD.lastModified, CURRENT_TIMESTAMP);
  • Eğer varsa eklemek belirterek CreateDate veya lastModified olmadan, onlar şimdiki zaman damgasına eşit ve seti olacak.
  • Eğer varsa güncellemek CreateDate veya lastModified belirtmeden onları, lastModified geçerli zaman damgasına kümesi olacaktır.

Ama işte güzel kısım:

  • Eğer varsa eklemek , bir belirtebilirsiniz şimdiki zaman damgası daha CreateDate yaşlı yaşlı zamanlardan ithalatı iyi çalışmasını sağlayan, (lastModified CreateDate eşit olacaktır).
  • Eğer varsa güncelleştirmek , bir belirtebilirsiniz önceki değerden daha eski lastModified bir yorumda bir yazım hatası tespit kozmetik değişiklikler (yapıyorsan bir girdi güncellemek için izin ( '0000-00-00 00:00:00' iyi çalışıyor) ) ve eski son Değiştirilen tarihi saklamak istiyorsunuz . Bu, son Değiştirilme tarihini değiştirmez.

21

MySQL 5.6'dan itibaren kolay-kolay ... bir deneyin:

create table tweet ( 
    id integer not null auto_increment primary key, 
    stamp_created timestamp default now(), 
    stamp_updated timestamp default now() on update now(),
    message varchar(163)
)

Muhtemelen harika çözüm Aradığım şey tetikleyici olmadan zaman sorunu yarat ve güncelle
matinict

Bu küçük sorunun çözülmesinin bu kadar uzun sürdüğüne inanamıyorum. Bunu düzelttiklerini bile bilmiyordum ve 2018 ... Teşekkürler.
hsanders

4

Bu sorun MySQL 5.6'da çözülmüş görünüyordu. Bunu MySQL 5.5'e kadar fark ettim; İşte örnek bir kod:

DROP TABLE IF EXISTS `provider_org_group` ;
CREATE TABLE IF NOT EXISTS `provider_org_group` (
  `id` INT NOT NULL,
  `name` VARCHAR(100) NOT NULL,
  `type` VARCHAR(100) NULL,
  `inserted` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `insert_src_ver_id` INT NULL,
  `updated` TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP,
  `update_src_ver_id` INT NULL,
  `version` INT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `id_UNIQUE` (`id` ASC),
  UNIQUE INDEX `name_UNIQUE` (`name` ASC))
ENGINE = InnoDB;

Bunu MySQL 5.5 üzerinde çalıştırmak şunları verir:

ERROR 1293 (HY000): Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause

Bunu MySQL 5.6'da çalıştırma

0 row(s) affected   0.093 sec


2

Mysql 5.7.21 için aşağıdakileri kullanıyorum ve iyi çalışıyor:

TABLO OLUŞTUR Posts( modified_atzaman damgası GÜNCELLEME CURRENT_TIMESTAMP'TA created_atVARSAYILAN CURRENT_TIMESTAMP BOŞ DEĞİL , zaman damgası BOŞ DEĞİL VARSAYILAN AKIM_TIMESTAMP)


1

bence bu, stamp_created ve stamp_updated için daha iyi bir sorgu

CREATE TABLE test_table( 
    id integer not null auto_increment primary key, 
    stamp_created TIMESTAMP DEFAULT now(), 
    stamp_updated TIMESTAMP DEFAULT '0000-00-00 00:00:00' ON UPDATE now() 
); 

çünkü kayıt oluşturulduğunda stamp_createddoldurulmalı now()ve stamp_updateddoldurulmalıdır'0000-00-00 00:00:00'


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.