时间戳自动更新无法使用ON DUPLICATE KEY UPDATE(PDO)

use*_*195 3 php mysql timestamp on-duplicate-key

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

CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Run Code Online (Sandbox Code Playgroud)

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");
Run Code Online (Sandbox Code Playgroud)

以下手动方法有效但不可取.

$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()");
Run Code Online (Sandbox Code Playgroud)

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

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;
Run Code Online (Sandbox Code Playgroud)

更新2:将timestamp设置为not null后的表结构

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;
Run Code Online (Sandbox Code Playgroud)

And*_*y W 7

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

`timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Run Code Online (Sandbox Code Playgroud)

尝试使其为NOT NULL - 因为你有它的有效默认值,MySQL不会抱怨你没有提供查询中的值:

`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Run Code Online (Sandbox Code Playgroud)

此外,尝试将timestamp字段重命名为更合理的内容,例如:

`changed_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Run Code Online (Sandbox Code Playgroud)

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

INSERT INTO folio(publication, productId) 
VALUES(:publication, :productId) 
ON DUPLICATE KEY UPDATE 
    publication=:publication, 
    productId=:productId
Run Code Online (Sandbox Code Playgroud)

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

UPDATE

似乎没有更新timestamp列是一个记录的行为 - TIMESTAMP列的MySQL手册

引用所需的段落:

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

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

因此,解决方案非常简单,您已经找到了 - timestamp只要您提供重复值,就会明确更新列,例如:

INSERT INTO folio(publication, productId) 
VALUES(:publication, :productId) 
ON DUPLICATE KEY UPDATE 
    `timestamp` = NOW()
Run Code Online (Sandbox Code Playgroud)

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