MySQL создает время и обновляет временную метку

Я создаю несколько таблиц, в которых хочу хранить время создания записи и ее последнего обновления. Я думал, что у меня может быть два поля временных меток, где одно будет иметь значение CURRENT_TIMESTAMP, а другое — CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP. Но я думаю, я не могу этого сделать, потому что у вас может быть только 1 поле метки времени со значением по умолчанию в таблице?

Как бы вы порекомендовали мне получить и хранить два раза? Спасибо!


person Aishwar    schedule 15.08.2010    source источник


Ответы (6)


Вы можете иметь два столбца типа timestamp в одной таблице.

Следующие работы для MySQL 5.0

create table t 
(
  id integer, 
  created_at timestamp default current_timestamp, 
  updated_at timestamp
);

Я думаю, вы путаете это с SQL Server (где отметка времени на самом деле не является «отметкой времени», и действительно существует ограничение на один столбец «отметка времени»)

Изменить: но вам понадобится триггер для обновления столбца update_at каждый раз, когда изменяется строка.

person a_horse_with_no_name    schedule 15.08.2010
comment
Это верно, временная метка SQL Server на самом деле является просто синонимом версии строки. - person SQLMenace; 15.08.2010
comment
Это будет выполнено, но поле updated_at не будет автоматически обновляться при изменении. Я думал, что добавление ON UPDATE CURRENT_TIMESTAMP в столбец updated_at позаботится об этом. То есть когда он жалуется, что это невозможно сделать. - person Aishwar; 15.08.2010
comment
Да, как я уже сказал: вам нужно использовать триггер для заполнения столбца updated_at - person a_horse_with_no_name; 15.08.2010

Хороший способ создать такие поля, как «создано» и «обновлено», это

CREATE TABLE `mytable` ( 
`id` INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, 
`created` TIMESTAMP DEFAULT '0000-00-00 00:00:00', 
`updated` TIMESTAMP DEFAULT now() ON UPDATE now(),
`myfield` VARCHAR(255)
); 

И при вставке необходимо ввести нули в оба столбца:

INSERT INTO mytable (created,updated,myfield) VALUES (null,null,'blablabla');

И теперь во всех обновлениях поле «обновлено» будет иметь новое значение с актуальной датой.

UPDATE mytable SET myfield='blablablablu' WHERE myfield='blablabla';

Источник: http://gusiev.com/2009/04/update-and-create-timestamps-with-mysql

person albert    schedule 22.02.2014
comment
Это лучшее решение, которое я нашел. Магия в том, что NULL преобразуется в NOW() при вставке. В типичном приложении будет больше способов обновить строку, чем создать ее, поэтому это похоже на меньшее обслуживание, чем использование вашего сейчас при создании и ручной обработке обновлений, с использованием отдельного триггера или другого подхода. - person botimer; 30.05.2015
comment
Замечательно сработало! Хотя в моей ситуации мне не нужно было передавать нулевые значения, и изменился только обновленный столбец. Кажется, работает хорошо. created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, ... - person Jordan; 07.11.2017
comment
это лучшее решение среди всех ответов здесь!! Большое спасибо, приятель - person Ashish Bainade; 19.10.2018

Начиная с версии MYSQL 5.6.5 вы можете сделать это, используя ПО УМОЛЧАНИЮ и ПРИ ОБНОВЛЕНИИ. Никаких триггеров не нужно.

ts_create TIMESTAMP ПО УМОЛЧАНИЮ CURRENT_TIMESTAMP,

ts_update TIMESTAMP ПО УМОЛЧАНИЮ CURRENT_TIMESTAMP ПРИ ОБНОВЛЕНИИ CURRENT_TIMESTAMP

person Dimitry    schedule 05.06.2015
comment
На данный момент это лучший ответ! - person v010dya; 24.09.2017
comment
Обратите внимание, что TIMESTAMP имеет верхний предел 2038-01-19 03:14:07. По моему опыту 18 лет проходят довольно быстро. Проблема с DATETIME, с другой стороны, заключается в том, что с UPDATE x='y', ts_update=NULL столбец обновления не преобразуется в текущую временную метку, а устанавливается в NULL, тогда как столбец TIMESTAMP по-прежнему устанавливается в текущую временную метку (по крайней мере, это то, что я найдено в MySQL 5.7). Так что решайте сами, какой из двух более приемлем для вашего варианта использования. - person Michael Härtl; 05.03.2020
comment
Кроме того, вы можете использовать синоним NOW() вместо CURRENT_TIMESTAMP для краткости. ts_create TIMESTAMP DEFAULT NOW(), ts_update TIMESTAMP DEFAULT NOW() ON UPDATE NOW() - person Peter Tarlos; 05.04.2020

Насколько я знаю, обходного пути для этого ограничения нет. Вам нужно будет вручную установить (как минимум) одну из временных меток, самый простой способ — просто добавить updated = NOW() к UPDATE-запросу.

person Guido Hendriks    schedule 15.08.2010
comment
+1 Это кажется рабочим решением. Мне бы очень понравилось, если бы сервер мог делать это автоматически :) - person Aishwar; 15.08.2010
comment
Возможно, с триггерами, но я думаю, что это не очень хорошее решение. - person Guido Hendriks; 15.08.2010
comment
Обычно делается наоборот: вы вручную указываете created=NOW(), а updated устанавливается автоматически. Причина в том, что вы создаете запись 1 раз, но обновления могут быть неограниченными. - person Stalinko; 23.02.2018

Вам понадобятся два столбца: CREATE_TIME и UPDATE_TIME.

Возможно, вы захотите добавить CREATE_USER и UPDATE_USER.

Возможно, вы захотите иметь отношения 1:many с измененным именем столбца, старыми и новыми значениями.

Все это является частью системы сбора измененных данных. У вас могут быть таблицы CDC, которые обновляются с помощью триггеров.

person duffymo    schedule 15.08.2010
comment
У меня есть 2 столбца для хранения времени создания и времени обновления, но я не могу установить два значения по умолчанию, указанные выше. Я посмотрю, что такое CDC. Разве не должно быть простого решения для этого? Я бы представил, что это обычный сценарий. - person Aishwar; 15.08.2010
comment
Это распространено, но я не верю, что в MySQL есть для этого встроенное решение. Oracle и SQL Server подходят. Сделать это несложно: несколько таблиц и триггеров. - person duffymo; 15.08.2010

Я бы оставил текущую метку времени так, как вы предложили, и заполнил поле created_at текущей датой при вставке.

person silvo    schedule 15.08.2010