Tại sao chỉ có một cột TIMESTAMP có mệnh đề CURRENT_TIMESTAMP trong mệnh đề DEFAULT?


180

Tại sao chỉ có một cột TIMESTAMP có mệnh đề CURRENT_TIMESTAMP trong mệnh đề DEFAULT hoặc ON 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;

Lỗi đó dẫn đến:

Mã lỗi: 1293

Định nghĩa bảng không chính xác; chỉ có thể có một cột TIMESTAMP với mệnh đề CURRENT_TIMESTAMP trong mệnh đề DEFAULT hoặc ON UPDATE


6
Nó thực sự tồi tệ hơn nhiều so với thông báo lỗi khiến nó trông như thế nào. Bạn không thể xác định một cột có CURRENT_TIMESTAMPin DEFAULThoặc ON UPDATEmệnh đề một khi có một cột có TIMESTAMPkiểu dữ liệu, bất kể nó có mệnh đề phụ hay không!
Nicolas Buduroi

9
Vì vậy, công việc này : CREATE TABLE foo (created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_on TIMESTAMP), nhưng không phải điều này:CREATE TABLE foo (updated_on TIMESTAMP, created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
Nicolas Buduroi

@NicolasBuduroi Không phải nếu timestampcột đầu tiên là null null. Nếu timestampcột đầu tiên not nullthì theo mặc định DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMPsẽ được thêm vào. stackoverflow.com/a/13544181/2859238
dùng104309

@NicolasBuduroi Cũng không nếu timestampcột đầu tiên có giá trị mặc định rõ ràng được đặt như thế nào default '0000-00-00 00:00:00'. Nếu cột không thể hoặc giá trị mặc định rõ ràng được đặt, thì DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMPsẽ KHÔNG được thêm
dùng104309

Sẽ thực sự thích nhìn thấy một câu trả lời về lý do tại sao? không phải làm thế nào để khắc phục nó hoặc làm thế nào nó cố định bây giờ. Tại sao điều này từng được thực hiện theo cách này? Nó có vẻ như là một cách hoàn toàn bản lĩnh và tôi không thể tìm thấy bất kỳ thiết kế / triển khai nào có thể là một lý do cho sự hạn chế này. Tôi muốn tìm hiểu làm thế nào người ngu chương trình, vì vậy xin vui lòng dạy tôi.
Lothar

Câu trả lời:


173

Hạn chế này, vốn chỉ vì lý do lịch sử, mã di sản, đã được gỡ bỏ trong các phiên bản gần đây của MySQL:

Thay đổi trong MySQL 5.6.5 (2012-04-10, Cột mốc 8)

Trước đây, nhiều nhất một cột TIMESTAMP trên mỗi bảng có thể được tự động khởi tạo hoặc cập nhật theo ngày và giờ hiện tại. Hạn chế này đã được dỡ bỏ. Bất kỳ định nghĩa cột TIMESTAMP nào cũng có thể có bất kỳ sự kết hợp nào giữa các mệnh đề DEFAULT CURRENT_TIMESTAMP và các mệnh đề CẬP NHẬT CURRENT_TIMESTAMP. Ngoài ra, các mệnh đề này hiện có thể được sử dụng với các định nghĩa cột DATETIME. Để biết thêm thông tin, hãy xem Khởi tạo và cập nhật tự động cho TIMESTAMP và DATETIME.

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


Kiểm tra @mooli trả lời dưới đây. Trên thực tế, cột dấu thời gian đầu tiên có "mặc định current_timestamp khi cập nhật current_timestamp" (vì vậy nó phải được đặt tên là update_at). Bạn chỉ cần đặt created_at thủ công tại thời điểm chèn.
Gismo Ranas

Chúng ta có thể làm gì nếu kết xuất mysql thuộc phiên bản 5.7 và thiết lập cần được chạy trên phiên bản 5.4
otc

1
@otc, bạn có thể chỉnh sửa bãi chứa hoặc bắt đầu lại với 5.4
Jasen

40

Tôi cũng đã tự hỏi rằng từ lâu rồi. Tôi đã tìm kiếm một chút trong lịch sử của mình và tôi nghĩ rằng bài đăng này: http://lists.mysql.com/iternals/34919 đại diện cho vị trí bán chính thức của MySQL (trước sự can thiệp của Oracle;))

Nói ngắn gọn:

giới hạn này chỉ bắt nguồn từ cách tính năng này hiện đang được triển khai trên máy chủ và không có lý do nào khác cho sự tồn tại của nó.

Vì vậy, lời giải thích của họ là "bởi vì nó được thực hiện như thế này". Nghe có vẻ không khoa học lắm. Tôi đoán tất cả xuất phát từ một số mã cũ. Điều này được đề xuất trong luồng trên: "thực hiện từ khi chỉ trường dấu thời gian đầu tiên là tự động thiết lập / cập nhật".

Chúc mừng!


Wow, thật là hôi thối. Hy vọng chúng tôi thấy một sửa chữa sớm.
BoltClock

46
Một hạn chế tuyệt vời khác của MySQL để chúng ta thưởng thức!
Nicolas Buduroi

1
@gorn giải pháp dễ dàng hơn / giải quyết xung quanh là giải pháp từ Scarlett bên dưới.
tihe

38

Chúng tôi có thể đưa ra một giá trị mặc định cho dấu thời gian để tránh vấn đề này.

Bài đăng này cung cấp một cách giải quyết chi tiết: http://gusiev.com/2009/04/update-and-create-timestamp-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() 
);

Lưu ý rằng cần phải nhập null vào cả hai cột trong khi "chè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

Quả thực là một lỗi thực hiện.

Cách tiếp cận riêng trong MySQL là tự cập nhật ngày tạo (nếu bạn cần) và khiến MySQL lo lắng về dấu thời gian update date ? update date : creation date như vậy:

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

Khi tạo Chèn NULL:

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

Các giá trị NULL cho dấu thời gian được xen kẽ là CURRENT_TIMESTAMP theo mặc định.

Trong MySQL, cột TIMESTAMP đầu tiên của bảng có cả thuộc tính DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMPthuộc tính, nếu không có thuộc tính nào được cung cấp cho nó. đây là lý do tại sao cột TIMESTAMP có thuộc tính phải xuất hiện trước hoặc bạn gặp lỗi được mô tả trong luồng này.


14
  1. Thay đổi kiểu dữ liệu của cột thành datetime
  2. Đặt kích hoạt

Nhu la:

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 ;

Tôi đã luôn xem xét phương pháp này ít hơn nhiều so với chức năng CURRENT_TIMESTAMP được triển khai một nửa.
TehShrike

1

Một cách khắc phục cho bạn có thể là đặt nó vào trường Cập nhật ngày và có một trình kích hoạt cập nhật trường Đã thêm với giá trị Cập nhật chỉ khi giá trị gia tăng là null.


1

Kết hợp nhiều câu trả lời:

Trong MySQL 5.5, DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMPkhông thể thêm vào DATETIMEmà chỉ bật TIMESTAMP.

Quy tắc:

1) tối đa một TIMESTAMPcột trên mỗi bảng có thể được tự động (hoặc thủ công [ Bổ sung của tôi ]) được khởi tạo hoặc cập nhật theo ngày và giờ hiện tại. (Tài liệu MySQL).

Vì vậy, chỉ có một TIMESTAMPcó thể có CURRENT_TIMESTAMPtrong DEFAULThoặc ON UPDATEmệnh đề

2) NOT NULL TIMESTAMPCột đầu tiên không có DEFAULTgiá trị rõ ràng như created_date timestamp default '0000-00-00 00:00:00'sẽ được đưa ra một cách ngầm định DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPvà do đó TIMESTAMPcác cột tiếp theo không thể được đưa ra CURRENT_TIMESTAMPtrên DEFAULThoặc ON UPDATEmệnh đề

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)

Tùy chọn khác (Nhưng updated_datelà cột đầu tiên):

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

Thử cái này:

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
Điều này sẽ làm việc nhưng nó không giải quyết vấn đề. created_at là 0 là loại vô dụng.
CompEng88

@ ComputerEngineer88 Đây là giải pháp phù hợp cho máy chủ mysql cũ. Bạn nên tự đặt created_atcột. Tôi nghĩ rằng đây là những gì op muốn nói có chủ ý.
Roger

đây chính xác là giải pháp chính thức, được ghi lại ở đây dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html
Rangi Lin

0

Đây là hạn chế trong phiên bản MYSQL 5.5. Bạn cần cập nhật phiên bản lên 5.6.

Error

Tôi đã gặp lỗi này khi thêm bảng trong MYSQL

Định nghĩa bảng không chính xác; chỉ có thể có một cột TIMESTAMP với CURRENT_TIMESTAMP trong mệnh đề DEFAULT hoặc ON UPDATE MYSQL mới của tôi

bảng trông giống như thế này.

tạo bảng tên_bảng (col1 int (5) auto_increment khóa chính, col2 varchar (300), col3 varchar (500), col4 int (3), col5 tinyint (2), col6 timestamp default default_timestamp, col7 timestamp default currentestimestest col8 tinyint (1) mặc định 0, col9 tinyint (1) mặc định 1);

Sau một thời gian đọc về những thay đổi trong các phiên bản MYSQL khác nhau và một số sự khác biệt. Tôi phát hiện ra rằng có một số thay đổi đã được thực hiện trong MYSQL phiên bản 5.6 so với phiên bản 5.5.

Bài viết này sẽ giúp bạn giải quyết vấn đề. http://www.oyewiki.com/MYQuery/Inc chính-table-def định-other-can-be-only-one-testestamp-column

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.