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

时间:2014-06-09 21:01:01

标签: php mysql timestamp on-duplicate-key

我已将时间戳设置为自动更新的表格作品集。

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;

3 个答案:

答案 0 :(得分:7)

据我所知,您的查询问题可能是因为您将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列是一种记录在案的行为 - MySQL manual for TIMESTAMP columns

引用所需的段落:

  

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

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

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

timestamp

无论如何,使INSERT INTO folio(publication, productId) VALUES(:publication, :productId) ON DUPLICATE KEY UPDATE `timestamp` = NOW() NOT NULL不会受到伤害。

答案 1 :(得分:1)

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

因此,作为一种尴尬的解决方法,您可以向表中添加一个虚拟字段,强制发生UPDATE(如果是重复的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

答案 2 :(得分:0)

只是

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

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

  • 您使用的是重复插入,替换还是忽略插入这三个中的哪个都没关系

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

只需在末尾添加created = current_timestamp即可手动完成。

很遗憾,就是这样!