6

我有一个时间戳设置为自动更新的表格作品集。

CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

PHP 中的 PDO 语句不会导致时间戳更新。

$statement = $this->connection->prepare("
INSERT INTO folio(publication, productId) 
VALUES(:publication, :productId) 
ON DUPLICATE KEY UPDATE 
id=LAST_INSERT_ID(id), publication=:publication, productId=:productId");

以下手动方法可行,但不可取。

$statement = $this->connection->prepare(
"INSERT INTO folio(publication, productId) 
VALUES(:publication, :productId) 
ON DUPLICATE KEY UPDATE 
id=LAST_INSERT_ID(id), publication=:publication, productId=:productId, timestamp=NOW()");

更新:这是我的作品集表结构

CREATE TABLE `folio` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `publication` varchar(255) DEFAULT NULL,
  `productId` varchar(255) DEFAULT NULL,
  `timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_folio` (`publication`,`productId`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

更新 2:将时间戳设置为不为空后的表结构

CREATE TABLE `folio` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `publication` varchar(255) DEFAULT NULL,
  `productId` varchar(255) DEFAULT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_folio` (`publication`,`productId`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
4

3 回答 3

10

据我所知,您的查询问题可能是因为您将timestamp字段设为空

`timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

尝试将其设为 NOT NULL - 因为您有有效的默认值,MySQL 不会抱怨您没有在查询中提供值:

`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

另外,尝试将timestamp字段重命名为更合理的名称,例如:

`changed_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

此外,正如我在评论中提到的 - 您不需要提供ON DUPLICATE KEY 部分中的所有字段,而只需要提供数据字段:

INSERT INTO folio(publication, productId) 
VALUES(:publication, :productId) 
ON DUPLICATE KEY UPDATE 
    publication=:publication, 
    productId=:productId

这是因为如果 MySQL 检测到您有重复的键条件,它不会插入新行,而是更新现有行,因此id列必须保持不变。

更新

似乎不更新timestamp列是记录在案的行为 - TIMESTAMP 列的 MySQL 手册

引用所需的段落:

如果该列是自动更新的,则当该行中任何其他列的值从其当前值更改时,它会自动更新为当前时间戳。如果所有其他列都设置为其当前值,则该列保持不变。为了防止该列在其他列更改时更新,请将其显式设置为其当前值。要在其他列未更改的情况下更新该列,请将其显式设置为应具有的值(例如,将其设置为 CURRENT_TIMESTAMP)。

因此,您满足所有条件:) - 当您插入记录时,应正确填充时间戳。但是,当您在更新时提供重复值时timestamp,MySQL 会看到您设置了行中已经存在的值(否则它不会重复),因此它不会更新timestamp列。

因此,解决方案很简单,您已经找到了 -timestamp每当您提供重复值时显式更新列,例如:

INSERT INTO folio(publication, productId) 
VALUES(:publication, :productId) 
ON DUPLICATE KEY UPDATE 
    `timestamp` = NOW()

无论如何,使timestampNOT NULL 不会受到伤害。

于 2014-06-09T21:15:55.467 回答
1

如果新的 INSERT 值与重复行中的旧值相同,则显然 MySQL 不执行 UPDATE,因此不会触发 ON UPDATE CURRENT_TIMESTAMP。:(

因此,作为一个尴尬的解决方法,您可以在表中添加一个虚拟字段,强制执行更新(在重复 id 的情况下):

$statement = $this->connection->prepare("
    INSERT INTO folio(publication, productId) 
      VALUES(:publication, :productId) 
      ON DUPLICATE KEY UPDATE 
      id=LAST_INSERT_ID(id), publication=:publication, productId=:productId,
      dummy = NOT dummy
");

...正如用户评论中所建议的那样:http: //dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

于 2014-06-09T22:13:02.810 回答
1

只是

在创建重复键更新时插入 your_table (a, b) 值 (?, ?) = current_timestamp

无论好坏,MySQL无论如何都不会在插入唯一类型调用的情况下默认更新时间戳。

  • 您使用的是 insert-on-dupe、replace、insert-ignore 这三个中的哪一个并不重要

  • 无论您在字段、表格或其他任何内容上使用哪些设置或质量,它都没有任何区别

它只需要通过created = current_timestamp在末尾添加来手动完成。

不幸的是,就是这样!

于 2020-03-02T18:21:35.207 回答