Neden DEFAULT yan tümcesinde CURRENT_TIMESTAMP içeren yalnızca bir TIMESTAMP sütunu olabilir?


180

Neden DEFAULT veya ON UPDATE deyiminde CURRENT_TIMESTAMP içeren yalnızca bir TIMESTAMP sütunu olabilir?

CREATE TABLE `foo` (
  `ProductID` INT(10) UNSIGNED NOT NULL,
  `AddedDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `UpdatedDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=INNODB;

Ortaya çıkan hata:

Hata Kodu: 1293

Yanlış tablo tanımı; DEFAULT veya ON UPDATE deyiminde CURRENT_TIMESTAMP içeren yalnızca bir TIMESTAMP sütunu olabilir


6
Aslında hata mesajının görünmesini sağlayan şeyden çok daha kötü. Fazladan bir cümle olsun, veri türünde bir sütun bulunduğunda CURRENT_TIMESTAMPin DEFAULTveya ON UPDATEyan tümcesine sahip bir sütun tanımlayamazsınız TIMESTAMP!
Nicolas Buduroi

9
Yani bu iş:, CREATE TABLE foo (created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_on TIMESTAMP)ama bu değil:CREATE TABLE foo (updated_on TIMESTAMP, created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
Nicolas Buduroi

@NicolasBuduroi İlk timestampsütun nullable ise yani null. İlk timestampsütun not nullvarsayılan olarak varsa DEFAULT CURRENT_TIMESTAMPve ON UPDATE CURRENT_TIMESTAMPeklenecektir. stackoverflow.com/a/13544181/2859238
user104309

@NicolasBuduroi İlk timestampsütunda açık varsayılan bir değer ayarlanmışsa da olmaz default '0000-00-00 00:00:00'. Sütun boş bırakılabilir veya açıkça varsayılan değer ayarlanmışsa, eklenmez DEFAULT CURRENT_TIMESTAMPve ON UPDATE CURRENT_TIMESTAMPKULLANILMAZ
user104309

Nedeniyle ilgili bir cevap görmek ister misiniz? nasıl başa çıkılacağı veya şimdi nasıl düzeltileceği değil. Bu neden bu şekilde uygulandı? Toplam bir braindead yolu gibi görünüyor ve bu kısıtlamanın bir nedeni olabilecek herhangi bir tasarım / uygulama bulamıyorum. Aptal insanların nasıl programlandığını öğrenmek istiyorum, bu yüzden lütfen bana öğret.
Lothar

Yanıtlar:


173

Yalnızca geçmiş kodların eski nedenlerinden kaynaklanan bu sınırlama, MySQL'in son sürümlerinde kaldırılmıştır:

MySQL 5.6.5'teki değişiklikler (2012-04-10, Milestone 8)

Önceden, tablo başına en fazla bir TIMESTAMP sütunu otomatik olarak geçerli tarih ve saate başlatılabilir veya 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. Ayrıca, bu maddeler artık DATETIME sütun tanımlarıyla birlikte kullanılabilir. Daha fazla bilgi için, bkz. TIMESTAMP ve DATETIME için Otomatik Başlatma ve Güncelleme.

http://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-5.html


Aşağıdaki @mooli yanıtını da kontrol edin. Aslında ilk zaman damgası sütununda "current_timestamp güncellemesinde varsayılan current_timestamp" otomatik olarak ayarlanmıştır (bu nedenle update_at olarak adlandırılmalıdır). Create_at öğesini ekleme zamanında manuel olarak ayarlamanız yeterlidir.
Gismo Ranas

mysql dökümü 5.7 sürümüne aitse ve kurulumun 5.4
otc

1
@otc, çöplüğü düzenleyebilir veya 5.4
Jasen

40

Bunu uzun zaman önce de merak ettim. Geçmişimde biraz araştırma yaptım ve bu yazının şu olduğunu düşünüyorum: http://lists.mysql.com/internals/34919 MySQL'in yarı resmi konumunu temsil ediyor (Oracle'ın müdahalesinden önce))

Kısacası:

bu sınırlama, yalnızca bu özelliğin sunucuda uygulanma biçiminden kaynaklanır ve varlığının başka bir nedeni yoktur.

Yani açıklamaları "çünkü bu şekilde uygulanmaktadır". Kulağa bilimsel gelmiyor. Sanırım her şey eski bir koddan geliyor. Bu, yukarıdaki iş parçacığında önerilir: "yalnızca ilk zaman damgası alanının otomatik olarak ayarlandığı / güncellendiği andan itibaren aktarma".

Şerefe!


Vay be, bu gerçekten kötü kokuyor. Umarım yakında bir düzeltme görürüz.
BoltClock

46
Zevk için bir başka büyük MySQL sınırlaması!
Nicolas Buduroi

1
@gorn daha kolay çözüm / çözüm aşağıdaki Scarlett'in çözümdür.
mühürlenir

38

Bu sorunu önlemek için zaman damgası için varsayılan bir değer verebiliriz.

Bu yayın ayrıntılı bir çözüm sunuyor: http://gusiev.com/2009/04/update-and-create-timestamps-with-mysql/

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

"Ekle" sırasında her iki sütuna da null değerlerin girilmesi gerektiğini unutmayın:

mysql> insert into test_table(stamp_created, stamp_updated) values(null, null); 
Query OK, 1 row affected (0.06 sec)
mysql> select * from t5; 
+----+---------------------+---------------------+ 
| 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) 

16

Gerçekten de bir uygulama hatası.

MySQL'deki yerel yaklaşım, bir oluşturma tarihini kendiniz güncellemek (gerekirse) ve MySQL'in zaman damgası hakkında endişelenmesini update date ? update date : creation datesağlamaktır:

CREATE TABLE tracked_data( 
  `data` TEXT,
  `timestamp`   TIMESTAMP,
  `creation_date` TIMESTAMP                                   
) ENGINE=INNODB; 

Oluşturulduğunda NULL Ekle:

INSERT INTO tracked_data(`data`,`creation_date`) VALUES ('creation..',NULL);

Zaman damgası için NULL değerler varsayılan olarak CURRENT_TIMESTAMP olarak kesilir.

MySQL bir tablonun ilk TIMESTAMP sütunu hem alır DEFAULT CURRENT_TIMESTAMPve ON UPDATE CURRENT_TIMESTAMPhiçbir nitelikler bunun için verilirse, öznitelik. Bu nedenle, özniteliklere sahip TIMESTAMP sütunu önce gelmelidir veya bu iş parçacığında açıklanan hatayı alırsınız.


14
  1. Sütunların veri türlerini datetime olarak değiştirme
  2. Tetikleyiciyi ayarla

Gibi:

DROP TRIGGER IF EXISTS `update_tablename_trigger`;
DELIMITER //
CREATE TRIGGER `update_tablename_trigger` BEFORE UPDATE ON `tablename`
 FOR EACH ROW SET NEW.`column_name` = NOW()
//
DELIMITER ;

Bu yöntemi her zaman yarı uygulanmış CURRENT_TIMESTAMP işlevselliğinden çok daha az janketi olarak düşündüm.
TehShrike

1

Sizin için bir düzeltme bunu UpdatedDate alanına koymak ve AddedDate alanını UpdatedDate değeri ile ancak AddedDate boşsa güncelleyen bir tetikleyici olabilir.


1

Çeşitli cevapları birleştirmek:

MySQL 5.5 sürümünde DEFAULT CURRENT_TIMESTAMPve sadece ON UPDATE CURRENT_TIMESTAMPeklenemez .DATETIMETIMESTAMP

Kurallar:

1) TIMESTAMPtablo başına en fazla bir sütun otomatik olarak (veya manuel olarak [ Eklemem ]) başlatılabilir veya geçerli tarih ve saate güncellenebilir. (MySQL Belgeleri).

Yani sadece tek TIMESTAMPolabilir CURRENT_TIMESTAMPbölgesi DEFAULTveya ON UPDATEfıkra

2) NOT NULL TIMESTAMPAçık bir DEFAULTdeğeri olmayan ilk sütuna created_date timestamp default '0000-00-00 00:00:00'dolaylı olarak verilecek DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPve bu nedenle sonraki TIMESTAMPsütunlara veya cümlesine verilemez CURRENT_TIMESTAMP.DEFAULTON UPDATE

CREATE TABLE `address` (
  `id` int(9) NOT NULL AUTO_INCREMENT,
  `village` int(11) DEFAULT NULL,
    `created_date` timestamp default '0000-00-00 00:00:00', 

    -- Since explicit DEFAULT value that is not CURRENT_TIMESTAMP is assigned for a NOT NULL column, 
    -- implicit DEFAULT CURRENT_TIMESTAMP is avoided.
    -- So it allows us to set ON UPDATE CURRENT_TIMESTAMP on 'updated_date' column.
    -- How does setting DEFAULT to '0000-00-00 00:00:00' instead of CURRENT_TIMESTAMP help? 
    -- It is just a temporary value.
    -- On INSERT of explicit NULL into the column inserts current timestamp.

-- `created_date` timestamp not null default '0000-00-00 00:00:00', // same as above

-- `created_date` timestamp null default '0000-00-00 00:00:00', 
-- inserting 'null' explicitly in INSERT statement inserts null (Ignoring the column inserts the default value)! 
-- Remember we need current timestamp on insert of 'null'. So this won't work. 

-- `created_date` timestamp null , // always inserts null. Equally useless as above. 

-- `created_date` timestamp default 0, // alternative to '0000-00-00 00:00:00'

-- `created_date` timestamp, 
-- first 'not null' timestamp column without 'default' value. 
-- So implicitly adds DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP. 
-- Hence cannot add 'ON UPDATE CURRENT_TIMESTAMP' on 'updated_date' column.


   `updated_date` timestamp null on update current_timestamp,

  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=132 DEFAULT CHARSET=utf8;

INSERT INTO address (village,created_date) VALUES (100,null);

mysql> select * from address;
+-----+---------+---------------------+--------------+
| id  | village | created_date        | updated_date |
+-----+---------+---------------------+--------------+
| 132 |     100 | 2017-02-18 04:04:00 | NULL         |
+-----+---------+---------------------+--------------+
1 row in set (0.00 sec)

UPDATE address SET village=101 WHERE village=100;

mysql> select * from address;
+-----+---------+---------------------+---------------------+
| id  | village | created_date        | updated_date        |
+-----+---------+---------------------+---------------------+
| 132 |     101 | 2017-02-18 04:04:00 | 2017-02-18 04:06:14 |
+-----+---------+---------------------+---------------------+
1 row in set (0.00 sec)

Diğer seçenek (Ama updated_dateilk sütundur):

CREATE TABLE `address` (
  `id` int(9) NOT NULL AUTO_INCREMENT,
  `village` int(11) DEFAULT NULL,
  `updated_date` timestamp null on update current_timestamp,
  `created_date` timestamp not null , 
  -- implicit default is '0000-00-00 00:00:00' from 2nd timestamp onwards

  -- `created_date` timestamp not null default '0000-00-00 00:00:00'
  -- `created_date` timestamp
  -- `created_date` timestamp default '0000-00-00 00:00:00'
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=132 DEFAULT CHARSET=utf8;

0

Bunu dene:

CREATE TABLE `test_table` (
`id` INT( 10 ) NOT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT 0,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE = INNODB;

3
Bu işe yarar ama sorunu çözmez. created_at 0 olan bir tür işe yaramaz.
CompEng88

@ ComputerEngineer88 Bu eski mysql sunucusu için doğru çözümdür. created_atSütunu kendiniz ayarlamanız gerekir . Bence bu kasten söylemek istediğim şeydir.
Roger

bu tam olarak resmi çözümdür, burada belgelenmiştir dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html
Rangi Lin

0

Bu MYSQL 5.5 sürümündeki sınırlamadır. Sürümü 5.6 olarak güncellemeniz gerekir.

Error

MYSQL'de bir tablo eklerken bu hatayı alıyordum

Yanlış tablo tanımı; DEFAULT veya ON UPDATE deyiminde CURRENT_TIMESTAMP içeren yalnızca bir TIMESTAMP sütunu olabilir Yeni MYSQL'im

tablo böyle bir şeye benziyor.

tablo oluştur tablo_adı (col1 int (5) auto_increment birincil anahtarı, col2 varchar (300), col3 varchar (500), col4 int (3), col5 tinyint (2), col6 zaman damgası varsayılan current_timestamp, col7 zaman damgası varsayılan current_timestamp güncellemesinde, col8 tinyint (1) varsayılan 0, col9 tinyint (1) varsayılan 1);

Bir süre sonra farklı MYSQL sürümlerindeki ve bazı googling değişikliklerini okuduktan sonra. Sürüm 5.5 üzerinde MYSQL sürüm 5.6 yapılan bazı değişiklikler olduğunu öğrendim.

Bu makale sorunu çözmenize yardımcı olacaktır. http://www.oyewiki.com/MYSQL/Incorrect-table-definition-there-can-be-only-one-timestamp-column

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.