Наличие в MySQL 4.0 столбцов меток времени "Создано" и "Последнее обновление"
У меня есть следующая схема таблицы;
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 во время каждой транзакции?
12 ответов
Один столбец TIMESTAMP в таблице может иметь текущую временную метку в качестве значения по умолчанию для инициализации столбца, в качестве значения автообновления или обоих. Невозможно, чтобы текущая временная метка была значением по умолчанию для одного столбца и значением автоматического обновления для другого столбца.
Ранее не более одного столбца TIMESTAMP на таблицу можно было автоматически инициализировать или обновить до текущей даты и времени. Это ограничение было снято. Любое определение столбца TIMESTAMP может содержать любую комбинацию предложений DEFAULT CURRENT_TIMESTAMP и ON UPDATE CURRENT_TIMESTAMP. Кроме того, эти предложения теперь можно использовать с определениями столбцов DATETIME. Для получения дополнительной информации см. Автоматическая инициализация и обновление для TIMESTAMP и DATETIME.
Есть хитрость, чтобы иметь обе отметки времени, но с небольшим ограничением.
Вы можете использовать только одно из определений в одной таблице. Создайте оба столбца отметок времени следующим образом:
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)
Вы можете иметь их обоих, просто снимите флаг "CURRENT_TIMESTAMP" на созданном поле. Всякий раз, когда вы создаете новую запись в таблице, просто используйте "NOW()" для значения.
Или же.
Напротив, удалите флаг "ON UPDATE CURRENT_TIMESTAMP" и отправьте NOW () для этого поля. Этот способ на самом деле имеет больше смысла.
Если вы решите, чтобы 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
Вот как вы можете иметь автоматические и гибкие поля 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' работает хорошо), что позволяет обновлять запись, если вы делаете косметические изменения (исправление опечатки в комментарии) и вы хотите сохранить старую дату последнего изменения. Это не изменит дату последнего изменения.
Начиная с MySQL 5.6, его легко-peasy... попробуйте:
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)
)
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()
);
источник: http://gusiev.com/2009/04/update-and-create-timestamps-with-mysql/
Эта проблема, кажется, была решена в 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
Я думаю, что это лучший запрос для 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'
Для MySQL 5.7.21 я использую следующее и отлично работает:
СОЗДАТЬ СТОЛ Posts
(modified_at
временная метка NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, created_at
временная метка NOT NULL DEFAULT CURRENT_TIMESTAMP)
это добавит два столбца для создания и обновления. оба будут обновляться при вставке и обновлении.
create table users(
id integer not null auto_increment primary key,
created_date timestamp default now(),
modified_date timestamp default now() on update now()
);
Мой веб-хостинг застрял на версии 5.1 mysql, поэтому любой, как я, не имеющий возможности обновления, может выполнить следующие указания:
http://joegornick.com/2009/12/30/mysql-created-and-modified-date-fields/