มีคอลัมน์เวลาประทับที่สร้างและอัปเดตล่าสุดใน MySQL 4.0


127

ฉันมีสคีมาตารางต่อไปนี้

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;

ล้มเหลวด้วยข้อผิดพลาดต่อไปนี้:

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

คำถามของฉันคือฉันสามารถมีทั้งสองช่องได้หรือไม่? หรือฉันต้องตั้งค่าฟิลด์ LastUpdated ด้วยตนเองระหว่างการทำธุรกรรมแต่ละครั้ง?


เฮ้ @Xenph Yan คุณช่วยเปลี่ยนคำตอบที่ "ยอมรับแล้ว" จากคำตอบที่ผิดเป็นคำตอบที่ถูกต้องได้ไหม คำตอบที่ยอมรับผิดนี้ทำให้ฉันเสียเวลาประมาณ 15 นาทีในการพยายามคิดว่าเกิดอะไรขึ้น ...
Bruno Reis

1
@BrunoReis เสร็จแล้วขอบคุณสำหรับการรับ
Xenph Yan

คำตอบ:


128

จากเอกสารMySQL 5.5 :

คอลัมน์ TIMESTAMP หนึ่งคอลัมน์ในตารางสามารถมีการประทับเวลาปัจจุบันเป็นค่าเริ่มต้นสำหรับการเริ่มต้นคอลัมน์เป็นค่าอัปเดตอัตโนมัติหรือทั้งสองอย่าง เป็นไปไม่ได้ที่จะกำหนดให้การประทับเวลาปัจจุบันเป็นค่าเริ่มต้นสำหรับคอลัมน์หนึ่งและค่าการอัปเดตอัตโนมัติสำหรับคอลัมน์อื่น

การเปลี่ยนแปลงในMySQL 5.6.5 :

ก่อนหน้านี้คอลัมน์ TIMESTAMP สูงสุดหนึ่งคอลัมน์ต่อตารางสามารถเริ่มต้นโดยอัตโนมัติหรืออัปเดตเป็นวันที่และเวลาปัจจุบัน ข้อ จำกัด นี้ถูกยกเลิก คำจำกัดความของคอลัมน์ TIMESTAMP สามารถมีค่า DEFAULT CURRENT_TIMESTAMP และ ON UPDATE CURRENT_TIMESTAMP ผสมกันได้ นอกจากนี้ตอนนี้สามารถใช้ส่วนคำสั่งเหล่านี้กับคำจำกัดความคอลัมน์ DATETIME ได้แล้ว สำหรับข้อมูลเพิ่มเติมโปรดดูการเริ่มต้นและการอัปเดตอัตโนมัติสำหรับ TIMESTAMP และ DATETIME


ที่มีการเปลี่ยนแปลง (อย่างน้อยใน MySQL 5.0) ดูเอกสารประกอบ: dev.mysql.com/doc/refman/5.0/en/timestamp.html
SimonSimCity

ตอบโต้ @SimonSimCity: เอกสารสำหรับ 5.0 พูดในสิ่งเดียวกันกับด้านบน
davemyron

5
@RobertGamble ฉันคิดว่าคำถามที่น่าสนใจกว่านั้นคือทำไม HECK ถึงไม่ได้ให้วิธีการทำงานที่ร้องขอ / จำเป็นโดยทั่วไปนี้
Ray

22
สิ่งนี้ดูเหมือนจะเป็นเรื่องเล็กน้อยในส่วนของ MySQL ใครสามารถอธิบายได้ว่าทำไมถึงเป็นเช่นนี้?
humble_coder

12
ความคิดเห็นเก่าจริงๆ แต่ในที่สุดมันก็เปลี่ยนไป: 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

มีเคล็ดลับที่จะมีทั้งการประทับเวลา แต่มีข้อ จำกัด เล็กน้อย

คุณสามารถใช้คำจำกัดความได้เพียงรายการเดียวในตารางเดียว สร้างคอลัมน์การประทับเวลาทั้งสองดังนี้:

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

โปรดทราบว่าจำเป็นต้องป้อนnullทั้งสองคอลัมน์ในระหว่าง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)  

นี่คือลิงค์จาก MySQL-Documentation ที่อธิบายถึงฟังก์ชันนั้น: dev.mysql.com/doc/refman/5.0/en/timestamp.html
SimonSimCity

6
กล่องรหัสแรกเมื่อป้อนด้วยตนเองทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน ขอบคุณ! ฉันหวังว่าฉันจะมี 'กรรม' มากพอที่จะเพิ่มคะแนนให้กับคำตอบนี้เพราะมันช่วยชีวิตเบคอนของฉันได้ mmmmm บันทึกเบคอน
amatusko

คุณต้องตรวจสอบให้แน่ใจว่าstamp_created ได้ตั้งค่าเป็น Not NULL แล้ว MySQL จะแทนที่ NULL ด้วยการประทับเวลาปัจจุบันโดยอัตโนมัติ
Valentin Despa

ทำไมคุณไม่สร้างstamp_createdฟิลด์เป็น: stamp_created timestamp default now()แทนที่จะใช้ค่า 'ZERO'
Sebastian Scholle

28

คุณสามารถมีทั้งสองอย่างได้เพียงแค่ถอดแฟล็ก "CURRENT_TIMESTAMP" ในฟิลด์ที่สร้างขึ้น เมื่อใดก็ตามที่คุณสร้างระเบียนใหม่ในตารางเพียงแค่ใช้ "NOW ()" สำหรับค่า

หรือ.

ในทางกลับกันให้ลบแฟล็ก 'ON UPDATE CURRENT_TIMESTAMP' และส่ง NOW () สำหรับฟิลด์นั้น วิธีนั้นเข้าท่ากว่า


2
วิธีนี้เป็นวิธีเดียวหรือไม่? ฉันไม่สามารถให้ฐานข้อมูลดูแลรายละเอียดทั้งหมดได้หรือไม่?
Xenph Yan

2
ตามคู่มือ MySql CURRENT_TIMESTAMP เป็นคำพ้องความหมายของ NOW () ดังนั้นฉันไม่คิดว่าจะได้ผล
tvanfosson

ฉันแน่ใจว่าคุณทำได้นั่นคือ CURRENT_TIMESTAMP เป็นธงที่สงวนไว้สำหรับฟิลด์เดียวเท่านั้น ไม่ว่าจะด้วยวิธีใดก็ตามหากคุณมีแฟล็กนั้นไม่ว่าคุณจะมีค่าใดสำหรับฟิลด์นั้นเมื่อคุณเพิ่มเร็กคอร์ดก็ตามค่านั้นจะเป็นการประทับเวลาปัจจุบันเสมอดังนั้นชื่อ
Stephen Walcher

1
@tvanfosson: การใช้ 'NOW ()' ในแบบสอบถามจะส่งต่อเวลาปัจจุบันไปยังฐานข้อมูล ค่าที่แท้จริงนั้นขึ้นอยู่กับภาษาเครื่องยนต์และอาจเป็นอีกร้อยอย่างที่ฉันไม่รู้ แฟล็กที่ฉันอ้างถึงตั้งค่าเพื่อให้เมื่อสร้างเรกคอร์ดเวลาจะถูกเพิ่มลงในฟิลด์นั้น
Stephen Walcher

2
ฉันใช้วิธีแทรก NOW () ส่วนใหญ่เนื่องจากโค้ดอื่นอาจแตะตารางเหล่านี้และฉันไม่ไว้ใจให้คนอัปเดตอย่างถูกต้อง :)
Xenph Yan

26

หากคุณตัดสินใจที่จะให้ MySQL จัดการการอัปเดตการประทับเวลาคุณสามารถตั้งค่าทริกเกอร์เพื่ออัปเดตฟิลด์ที่แทรกได้

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

MySQL อ้างอิง: http://dev.mysql.com/doc/refman/5.0/en/triggers.html


นี่คือสิ่งที่ฉันกำลังมองหา ฉันไม่ต้องการพึ่งพาคนที่เพิ่ม NOW () ลงในแบบสอบถาม!
บอท

จริงๆแล้วมันจะดีกว่าถ้าทำหลังจากใส่แล้วตั้งค่าใหม่ <timestamp_field> = ใหม่ <timestamp_field ที่ต้องมีค่าเริ่มต้น current_timestamp> ด้วยวิธีนี้ทั้งสองช่องจะ
ห่างกัน

@KacieHouser ไม่อนุญาตให้อัปเดตแถวใหม่ในภายหลังทริกเกอร์
โทมัส

23

นี่คือวิธีที่คุณสามารถมีช่อง createDate / lastModified อัตโนมัติและยืดหยุ่นโดยใช้ทริกเกอร์:

ก่อนอื่นให้กำหนดดังนี้:

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`),
)

จากนั้นเพิ่มทริกเกอร์เหล่านี้:

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);
  • หากคุณแทรกโดยไม่ระบุ createDate หรือ lastModified ค่าเหล่านี้จะเท่ากันและตั้งค่าเป็นการประทับเวลาปัจจุบัน
  • หากคุณอัปเดตโดยไม่ระบุ createDate หรือ lastModified lastModified จะถูกตั้งค่าเป็นการประทับเวลาปัจจุบัน

แต่นี่คือส่วนที่ดี:

  • หากคุณแทรกคุณสามารถระบุcreateDate ที่เก่ากว่าการประทับเวลาปัจจุบันทำให้การนำเข้าจากเวลาเก่าทำงานได้ดี (lastModified จะเท่ากับ createDate)
  • หากคุณอัปเดตคุณสามารถระบุlastModified ที่เก่ากว่าค่าก่อนหน้า ('0000-00-00 00:00:00' ทำงานได้ดี) ช่วยให้สามารถอัปเดตรายการได้หากคุณกำลังทำการเปลี่ยนแปลงเครื่องสำอาง (แก้ไขการพิมพ์ผิดในความคิดเห็น ) และคุณต้องการเก็บวันที่แก้ไขล่าสุดไว้ สิ่งนี้จะไม่แก้ไขวันที่แก้ไขล่าสุด

21

ในขณะที่ MySQL 5.6 นั้นง่ายต่อการใช้งาน ... ลองดูสิ:

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

อาจเป็นทางออกที่ยอดเยี่ยมสิ่งที่ฉันกำลังค้นหาสร้างและอัปเดตปัญหาเวลาโดยไม่มีทริกเกอร์
matinict

ฉันไม่อยากจะเชื่อเลยว่ามันใช้เวลานานขนาดนี้ในการแก้ไขความรำคาญเล็กน้อยนี้ ฉันไม่รู้ด้วยซ้ำว่าพวกเขาแก้ไขสิ่งนี้และมันเป็นปี 2018 ... ขอบคุณ
hsanders

4

ปัญหานี้ดูเหมือนจะได้รับการแก้ไขแล้วใน MySQL 5.6 ฉันสังเกตเห็นสิ่งนี้จนถึง MySQL 5.5; นี่คือรหัสตัวอย่าง:

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;

การรันบน MySQL 5.5 ช่วยให้:

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

เรียกใช้สิ่งนี้บน MySQL 5.6

0 row(s) affected   0.093 sec


2

สำหรับ mysql 5.7.21 ฉันใช้สิ่งต่อไปนี้และใช้งานได้ดี:

สร้างตารางPosts(การ modified_atประทับเวลาไม่ใช่ NULL DEFAULT CURRENT_TIMESTAMP ในการอัปเดต CURRENT_TIMESTAMP การ created_atประทับเวลาไม่ใช่ CURRENT_TIMESTAMP เริ่มต้นที่เป็นศูนย์)


1

ฉันคิดว่านี่เป็นแบบสอบถามที่ดีกว่าสำหรับ stamp_created และ stamp_updated

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

เพราะเมื่อสร้างเรกคอร์ดstamp_createdควรกรอกnow()และstamp_updatedควรกรอก'0000-00-00 00:00:00'


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.