เหตุใดจึงมีคอลัมน์ TIMESTAMP เพียงคอลัมน์เดียวที่มี CURRENT_TIMESTAMP ในส่วนเริ่มต้น


180

เหตุใดจึงมีเพียงคอลัมน์ TIMESTAMP เพียงคอลัมน์เดียวที่มี CURRENT_TIMESTAMP ในค่าเริ่มต้นหรือตามข้อ UPDATE

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;

ข้อผิดพลาดที่เป็นผล:

รหัสข้อผิดพลาด: 1293

คำจำกัดความของตารางไม่ถูกต้อง สามารถมีได้เพียงหนึ่งคอลัมน์ TIMESTAMP ที่มี CURRENT_TIMESTAMP ในค่าเริ่มต้นหรือตามข้อ UPDATE


6
จริงๆแล้วมันแย่กว่าข้อความแสดงข้อผิดพลาด คุณไม่สามารถกำหนดคอลัมน์ด้วยCURRENT_TIMESTAMPในDEFAULTหรือON UPDATEประโยคเมื่อมีคอลัมน์ที่มีTIMESTAMPชนิดข้อมูลไม่ว่าจะมีส่วนคำสั่งพิเศษ!
Nicolas Buduroi

9
ดังนั้นงานนี้: CREATE TABLE foo (created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_on TIMESTAMP)แต่ไม่ใช่สิ่งนี้:CREATE TABLE foo (updated_on TIMESTAMP, created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
Nicolas Buduroi

@NicolasBuduroi ไม่ได้ถ้าคนแรกที่คอลัมน์เช่นtimestamp nullable nullหากtimestampคอลัมน์แรกnot nullนั้นเป็นค่าเริ่มต้นDEFAULT CURRENT_TIMESTAMPและON UPDATE CURRENT_TIMESTAMPจะถูกเพิ่ม stackoverflow.com/a/13544181/2859238
user104309

@NicolasBuduroi นอกจากนี้ยังไม่ได้ถ้าครั้งแรกคอลัมน์มีชุดค่าเริ่มต้นอย่างชัดเจนเช่นtimestamp default '0000-00-00 00:00:00'หากคอลัมน์นั้นเป็นโมฆะหรือตั้งค่าเริ่มต้นอย่างชัดเจนแล้วDEFAULT CURRENT_TIMESTAMPและON UPDATE CURRENT_TIMESTAMPจะไม่ถูกเพิ่ม
user104309

ชอบที่จะเห็นคำตอบเกี่ยวกับสาเหตุหรือไม่ ไม่ใช่วิธีการแก้ไขหรือวิธีแก้ไขในขณะนี้ ทำไมสิ่งนี้ถึงถูกนำมาใช้ในวิธีนี้? ดูเหมือนว่าจะเป็นวิธีการพัฒนาสมองโดยรวมและฉันไม่พบการออกแบบ / การนำไปใช้ใด ๆ ที่อาจเป็นสาเหตุของข้อ จำกัด นี้ ฉันต้องการเรียนรู้วิธีการเขียนโปรแกรมคนโง่ดังนั้นโปรดสอนฉัน
Lothar

คำตอบ:


173

ข้อ จำกัด นี้ซึ่งเกิดจากเหตุผลในอดีตเหตุผลของรหัสดั้งเดิมได้ถูกยกขึ้นใน MySQL เวอร์ชันล่าสุด:

การเปลี่ยนแปลงใน MySQL 5.6.5 (2012-04-10, Milestone 8)

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

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


ตรวจสอบด้วย @mooli คำตอบด้านล่าง ที่จริงแล้วคอลัมน์การประทับเวลาแรกมี "ค่าเริ่มต้น current_timestamp ในการอัปเดต current_timestamp" ตั้งค่าโดยอัตโนมัติ (ดังนั้นจึงควรตั้งชื่อว่า updated_at) คุณต้องตั้งค่า created_at ด้วยตนเองในเวลาที่แทรก
Gismo Ranas

เราจะทำอย่างไรถ้าการถ่ายโอนข้อมูล mysql เป็นของรุ่น 5.7 และการตั้งค่าจะต้องทำงานใน 5.4
otc

1
@otc คุณสามารถแก้ไขการถ่ายโอนข้อมูลหรือเริ่มใหม่ด้วย 5.4
Jasen

40

ฉันก็สงสัยมานานแล้วเช่นกัน ฉันค้นหาเล็กน้อยในประวัติศาสตร์ของฉันและฉันคิดว่าโพสต์นี้: http://lists.mysql.com/internals/34919แสดงถึงตำแหน่งกึ่งทางการของ MySQL (ก่อนการแทรกแซงของ Oracle;)

ในระยะสั้น:

ข้อ จำกัด นี้เกิดจากวิธีการใช้งานคุณลักษณะนี้ในเซิร์ฟเวอร์ในปัจจุบันและไม่มีเหตุผลอื่นใดที่มีอยู่

ดังนั้นคำอธิบายของพวกเขาคือ "เพราะมันถูกนำไปใช้เช่นนี้" ไม่ฟังทางวิทยาศาสตร์มาก ฉันเดาว่ามันมาจากรหัสเก่าบางอัน สิ่งนี้แนะนำในเธรดด้านบน: "การดำเนินการเมื่อมีเพียงฟิลด์การประทับเวลาแรกเท่านั้นที่เป็น auto-set / update"

ไชโย!


ว้าวนั่นมันเหม็นจริงๆ หวังว่าเราจะเห็นการแก้ไขในไม่ช้า
BoltClock

46
ข้อ จำกัด อีกอย่างหนึ่งของ MySQL ที่ดีสำหรับเราที่จะสนุกได้เลย!
Nicolas Buduroi

1
@gorn วิธีแก้ปัญหา / แก้ไขที่ง่ายกว่านั้นมาจาก Scarlett ด้านล่าง
thehe

38

เราสามารถให้ค่าเริ่มต้นสำหรับการประทับเวลาเพื่อหลีกเลี่ยงปัญหานี้

โพสต์นี้จะให้วิธีแก้ปัญหาอย่างละเอียด: 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() 
);

โปรดทราบว่ามีความจำเป็นต้องใส่ค่า 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 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

อันที่จริงข้อผิดพลาดในการใช้งาน

วิธีการเนทีฟใน MySQL คือการอัพเดทวันที่สร้างด้วยตัวเอง (ถ้าคุณต้องการ) และทำให้ MySQL กังวลเกี่ยวกับการประทับเวลา update date ? update date : creation dateเช่นนั้น:

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

ในการสร้างแทรก NULL:

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

ค่า NULL สำหรับการประทับเวลาถูกรบกวนเป็น CURRENT_TIMESTAMP โดยค่าเริ่มต้น

ใน MySQL คอลัมน์ TIMESTAMP แรกของตารางจะได้รับทั้งสองDEFAULT CURRENT_TIMESTAMPและON UPDATE CURRENT_TIMESTAMPคุณลักษณะหากไม่มีแอตทริบิวต์ให้ นี่คือสาเหตุที่คอลัมน์ TIMESTAMP ที่มีแอตทริบิวต์ต้องมาก่อนหรือคุณได้รับข้อผิดพลาดที่อธิบายไว้ในชุดข้อความนี้


14
  1. เปลี่ยนชนิดข้อมูลของคอลัมน์เป็นวันที่และเวลา
  2. ตั้งค่าทริกเกอร์

เช่น:

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 ;

ฉันมักจะพิจารณาวิธีการนี้ความไม่แน่นอนมากกว่าฟังก์ชั่น CURRENT_TIMESTAMP
TehShrike

1

การแก้ไขที่ดีสำหรับคุณคือการวางไว้ในเขตข้อมูล UpdatedDate และมีทริกเกอร์ที่อัปเดตฟิลด์ AddDate ด้วยค่าอัปเดตเฉพาะเมื่อ AddDate เป็นโมฆะเท่านั้น


1

การรวมคำตอบต่าง ๆ :

ใน MySQL 5.5 DEFAULT CURRENT_TIMESTAMPและON UPDATE CURRENT_TIMESTAMPไม่สามารถเพิ่มในแต่เฉพาะบนDATETIMETIMESTAMP

กฎ:

1) อย่างน้อยหนึ่งTIMESTAMPคอลัมน์ต่อตารางอาจเป็นอัตโนมัติ (หรือด้วยตนเอง [การเพิ่มของฉัน ]) ที่กำหนดค่าเริ่มต้นหรืออัปเดตเป็นวันที่และเวลาปัจจุบัน (เอกสาร MySQL)

ดังนั้นมีเพียงคนเดียวที่TIMESTAMPสามารถมีCURRENT_TIMESTAMPในDEFAULTหรือON UPDATEมาตรา

2) เป็นครั้งแรกในNOT NULL TIMESTAMPคอลัมน์ได้โดยไม่ต้องอย่างชัดเจนDEFAULTเช่นค่าcreated_date timestamp default '0000-00-00 00:00:00'จะได้รับปริยายDEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPและด้วยเหตุที่ตามมาTIMESTAMPคอลัมน์ไม่สามารถให้CURRENT_TIMESTAMPบนDEFAULTหรือON 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)

ตัวเลือกอื่น ๆ (แต่updated_dateเป็นคอลัมน์แรก):

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

ลองสิ่งนี้:

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
มันจะใช้งานได้ แต่มันไม่สามารถแก้ปัญหาได้ created_at คือ 0 ซึ่งไร้ประโยชน์
CompEng88

@ ComputerEngineer88 นี่เป็นโซลูชันที่เหมาะสมสำหรับเซิร์ฟเวอร์ mysql รุ่นเก่า คุณควรตั้งค่าcreated_atคอลัมน์ด้วยตัวเอง ฉันคิดว่านี่คือสิ่งที่ op ต้องการพูดอย่างตั้งใจ
Roger

ตรงนี้เป็นวิธีการแก้ปัญหาอย่างเป็นทางการเอกสารที่นี่dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html
Rangi หลิน

0

นี่เป็นข้อ จำกัด ในรุ่น MYSQL 5.5 คุณต้องอัปเดตเวอร์ชันเป็น 5.6

Error

ฉันได้รับข้อผิดพลาดนี้ในการเพิ่มตารางใน MYSQL

คำจำกัดความของตารางไม่ถูกต้อง สามารถมีได้เพียงหนึ่งคอลัมน์ TIMESTAMP ที่มี CURRENT_TIMESTAMP ในค่าเริ่มต้นหรือในข้อ UPDATE MYSQL ใหม่ของฉัน

ตารางมีลักษณะเช่นนี้

สร้างตาราง table_name (col1 int (5) คีย์หลัก auto_increment, col2 varchar (300), col3 varchar (500), col4 int (3), col5 Tinyint (2), col6 เวลาบันทึกเริ่มต้น current_timestamp, col7 ประทับเวลาเริ่มต้น current_timestamp ปัจจุบัน col8 tinyint (1) ค่าเริ่มต้น 0, col9 tinyint (1) ค่าเริ่มต้น 1);

หลังจากเวลาอ่านเกี่ยวกับการเปลี่ยนแปลงในรุ่น MYSQL ที่แตกต่างกันและ googling บางส่วน ฉันพบว่ามีการเปลี่ยนแปลงบางอย่างที่เกิดขึ้นใน MYSQL รุ่น 5.6 มากกว่าเวอร์ชั่น 5.5

บทความนี้จะช่วยคุณแก้ไขปัญหา http://www.oyewiki.com/MYSQL/Incorrect-table-definition-there-can-be-only-one-timestamp-column

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