Có cả cột dấu thời gian được tạo và cập nhật lần cuối trong MySQL 4.0


127

Tôi có lược đồ bảng sau;

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;

Nó không thành công với lỗi sau:

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

Câu hỏi của tôi là, tôi có thể có cả hai lĩnh vực đó không? hoặc tôi phải đặt thủ công trường LastUpdated trong mỗi giao dịch?


Này, @Xenph Yan, bạn có phiền khi thay đổi câu trả lời "Được chấp nhận" từ câu trả lời sai hiện tại sang câu trả lời đúng không? Câu trả lời sai, được chấp nhận này khiến tôi mất khoảng 15 phút để cố gắng tìm hiểu chuyện gì đang xảy ra ...
Bruno Reis

1
@BrunoReis Xong, cảm ơn vì đã chọn.
Xenph Yan

Câu trả lời:


128

Từ tài liệu MySQL 5.5 :

Một cột TIMESTAMP trong bảng có thể có dấu thời gian hiện tại làm giá trị mặc định để khởi tạo cột, dưới dạng giá trị tự động cập nhật hoặc cả hai. Không thể có dấu thời gian hiện tại là giá trị mặc định cho một cột và giá trị tự động cập nhật cho cột khác.

Thay đổi trong MySQL 5.6.5 :

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.


Điều đó đã thay đổi (ít nhất là trong MySQL 5.0). Xem tài liệu: dev.mysql.com/doc/refman/5.0/en/timestamp.html
SimonSimCity

Truy cập @SimonSimCity: Các tài liệu cho 5.0 nói chính xác điều tương tự như trên.
davemyron

5
@RobertGamble Tôi nghĩ rằng câu hỏi thú vị hơn sẽ là TẠI SAO HECK KHÔNG cung cấp cách thức thực hiện chức năng cần thiết / yêu cầu rất phổ biến này.
Ray

22
Điều này có vẻ hơi độc đoán về phía MySQL. Bất cứ ai có thể giải thích tại sao đây là trường hợp?
humble_coder

12
Nhận xét thực sự thực sự cũ, NHƯNG, cuối cùng nó đã được thay đổi: 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

Có một mẹo để có cả dấu thời gian, nhưng với một chút hạn chế.

Bạn chỉ có thể sử dụng một trong các định nghĩa trong một bảng. Tạo cả hai cột dấu thời gian như vậy:

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 nullvào cả hai cột trong 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)  

Đây là một liên kết từ Tài liệu MySQL mô tả chức năng đó: dev.mysql.com/doc/refman/5.0/en/timestamp.html
SimonSimCity

6
hộp mã đầu tiên, khi được nhập thủ công hoạt động hoàn hảo cho tôi. Cảm ơn! Tôi ước tôi có đủ 'nghiệp chướng' để nâng cao câu trả lời này vì nó đã cứu được thịt xông khói của tôi. mmmmm lưu thịt xông khói.
amatusko

Bạn cần chắc chắn rằng stamp_created nó cũng được đặt là KHÔNG NULL. MySQL sẽ tự động thay thế NULL bằng dấu thời gian hiện tại.
Valentin Despa

Tại sao bạn cũng không tạo stamp_createdtrường dưới dạng: stamp_created timestamp default now()thay vì sử dụng giá trị 'ZERO'?
Sebastian Scholle

28

Bạn có thể có cả hai, chỉ cần tắt cờ "CURRENT_TIMESTAMP" trên trường đã tạo. Bất cứ khi nào bạn tạo một bản ghi mới trong bảng, chỉ cần sử dụng "NOW ()" cho một giá trị.

Hoặc là.

Ngược lại, xóa cờ 'TRÊN CẬP NHẬT CURRENT_TIMESTAMP' và gửi NOW () cho trường đó. Cách đó thực sự có ý nghĩa hơn.


2
đây có phải cách duy nhất không? Tôi không thể có cơ sở dữ liệu xem xét tất cả các chi tiết?
Xenph Yan

2
Theo hướng dẫn của MySql, CURRENT_TIMESTAMP là từ đồng nghĩa với NOW () vì vậy tôi không nghĩ rằng nó sẽ hoạt động.
tvanfosson

Tôi chắc chắn rằng bạn có thể, chỉ là CURRENT_TIMESTAMP là một cờ chỉ dành riêng cho một trường. Dù bằng cách nào, nếu bạn có cờ đó trong đó, bất kể giá trị nào bạn có cho trường đó khi bạn thêm một bản ghi, nó sẽ luôn là dấu thời gian hiện tại, do đó là tên.
Stephen Walcher

1
@tvanfosson: Sử dụng 'NOW ()' trong truy vấn sẽ chuyển thời gian hiện tại vào cơ sở dữ liệu. Giá trị đó thực sự phụ thuộc vào ngôn ngữ, động cơ và có thể là hàng trăm thứ khác mà tôi không biết. Cờ tôi đã đề cập để đặt nó để khi bản ghi được tạo, thời gian được thêm vào trường đó.
Stephen Walcher

2
Tôi đã sử dụng cách chèn NOW (), chủ yếu là vì các mã khác có thể chạm vào các bảng này và tôi không tin mọi người cập nhật chúng chính xác. :)
Xenph Yan

26

Nếu bạn quyết định để MySQL xử lý việc cập nhật dấu thời gian, bạn có thể thiết lập trình kích hoạt để cập nhật trường khi chèn.

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

Tham khảo MySQL: http://dev.mysql.com/doc/refman/5.0/en/triggers.html


Rất vui vì đây là thứ tôi đang tìm kiếm. Tôi không muốn phải dựa vào những người đã thêm NOW () vào truy vấn!
Bot

thực sự sẽ tốt hơn để làm sau khi chèn và đặt MỚI. <timestamp_field> = new. <timestamp_field thực sự phải có current_timestamp> theo cách này cả hai trường đều nhất quán
KacieHouser

@KacieHouser Không được phép cập nhật hàng MỚI sau khi kích hoạt
Thomas

23

Đây là cách bạn có thể có các trường createdDate / lastModified tự động & linh hoạt bằng cách sử dụng kích hoạt:

Đầu tiên xác định chúng như thế này:

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

Sau đó thêm các kích hoạt này:

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);
  • Nếu bạn chèn mà không chỉ định createDate hoặc lastModified, chúng sẽ bằng nhau và được đặt thành dấu thời gian hiện tại.
  • Nếu bạn cập nhật chúng mà không chỉ định createdDate hoặc lastModified, lastModified sẽ được đặt thành dấu thời gian hiện tại.

Nhưng đây là phần hay:

  • Nếu bạn chèn , bạn có thể chỉ định một createdDate cũ hơn dấu thời gian hiện tại , cho phép nhập từ thời gian cũ hoạt động tốt (lastModified sẽ bằng với createdDate).
  • Nếu bạn cập nhật , bạn có thể chỉ định một LastModified cũ hơn giá trị trước đó ('0000-00-00 00:00:00' hoạt động tốt), cho phép cập nhật một mục nếu bạn đang thay đổi mỹ phẩm (sửa lỗi chính tả trong một nhận xét ) và bạn muốn giữ ngày cũ cuối cùng . Điều này sẽ không sửa đổi ngày cuối cùng.

21

Kể từ MySQL 5.6, nó dễ dàng ... hãy thử xem:

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

Có lẽ là giải pháp tuyệt vời Những gì tôi đang tìm kiếm tạo và cập nhật vấn đề thời gian mà không cần kích hoạt
chiếu vào

Tôi không thể tin rằng phải mất nhiều thời gian để sự phiền toái nhỏ này được giải quyết. Tôi thậm chí không nhận ra họ đã sửa lỗi này và đó là năm 2018 ... Cảm ơn.
hsanders 16/03/18

4

Vấn đề này dường như đã được giải quyết trong MySQL 5.6. Tôi đã nhận thấy điều này cho đến khi MySQL 5.5; đây là một mã ví dụ:

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;

Chạy cái này trên MySQL 5.5 mang lại:

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

Chạy cái này trên MySQL 5.6

0 row(s) affected   0.093 sec


2

Đối với mysql 5.7.21 tôi sử dụng như sau và hoạt động tốt:

TẠO BẢNG Posts( modified_atdấu thời gian KHÔNG NULL DEFAULT CURRENT_TIMESTAMP TRÊN CẬP NHẬT CURRENT_TIMESTAMP, created_atdấu thời gian KHÔNG NULL DEFAULT CURRENT_TIMESTAMP)


1

Tôi nghĩ rằng đây là truy vấn tốt hơn cho tem_created và tem_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() 
); 

bởi vì khi bản ghi được tạo, stamp_creatednên được điền bởi now()stamp_updatednên được điền bởi'0000-00-00 00:00:00'


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.