Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 时间戳自动更新不适用于重复密钥更新(PDO)_Php_Mysql_Timestamp_On Duplicate Key - Fatal编程技术网

Php 时间戳自动更新不适用于重复密钥更新(PDO)

Php 时间戳自动更新不适用于重复密钥更新(PDO),php,mysql,timestamp,on-duplicate-key,Php,Mysql,Timestamp,On Duplicate Key,我有一张时间戳设置为自动更新的对折表 CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP $statement = $this->connection->prepare(" INSERT INTO folio(publication, productId) VALUES(:publication, :productId) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), publication

我有一张时间戳设置为自动更新的对折表

CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
$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");
PHP中的PDO语句不会导致时间戳更新

CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
$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;

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

`timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
尝试将其设置为非空-因为您有有效的默认值,MySQL不会抱怨您没有在查询中提供该值:

`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
另外,尝试将
时间戳
字段重命名为更合理的名称,例如:

`changed_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
另外,正如我在评论中提到的,您不需要在重复键上的
部分提供所有字段,只需要提供数据字段:

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

更新

似乎不更新
时间戳
列是一种记录在案的行为-

引用所需段落:

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

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

因此,解决方案很简单,而且您已经找到了—只要提供重复值,就显式更新
timestamp
列,例如:


无论如何,将
时间戳设置为非空不会有什么坏处。

如果新的插入值与重复行中的旧值相同,则MySQL显然不会执行更新,因此不会触发更新时的当前时间戳。:(

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

…正如这里的用户评论所建议的:

它只是

将创建的重复密钥更新=当前时间戳时的值(?,)插入_表(a,b)

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

  • 这三个选项中的哪一个无关紧要,重复插入、替换、插入忽略您正在使用的

  • 您在字段、表格或任何其他内容上使用的设置或质量没有任何区别

只需在末尾添加
created=current\u timestamp
即可手动完成


不幸的是,就是这样!

请发布
对开本
表结构。此外,您的查询也有问题-无需更新重复键
部分的
中的所有字段,只需更新
出版物
产品ID
。而且-将您的字段命名为
时间戳
是非常糟糕的主意,因为它是保留字。@AndyW用表更新了问题structure@AndyW也没有告诉你“无需更新重复密钥中的所有字段”也许你在代码中的回答会澄清这一点,因为publication和productID的值与重复行中相应列的值不同吗?请阅读此处用户注释下的第二条注释:“如果没有任何更改,这将不起作用,可能是因为MySQL根本不运行虚拟更新。”@bloodyKnuckles似乎是这样的,我只有publication和productId要检查,它们是execute语句中唯一要更新/插入的字段,这意味着它要进行虚拟更新,因此作为一种解决方法,我将使用timestamp=NOW()在我的查询中,请注意:恐怕设置NOTNULL以及重命名字段都不起作用,而且您关于提供所有字段的观点仍然不清楚(您的查询与我的查询类似,我只是更新publication和productId p.s。两者都是复合唯一键)此外,我还使用了mysql保留字时间戳的反勾号来避开它,它工作得很好。您是否尝试设置为
非空
或只是猜测?我有一个系统,大约有100个表,其中大多数都使用自动更新的时间戳列-一切都像一个符咒。所有这些列都是
非空
,很明显因此,这是我在您的代码中注意到的第一件事。在Not Null之后更新了表结构,我是否也应该发布和productId NN?这完全取决于您对数据模型的要求-将某个字段设置为Null意味着您声明“此字段有时可以接受未知值,我可以接受”。自动更新的时间戳字段有点不同,因为MySQL将其视为“神奇的”,因此一些选项(如nullability)可能会打破这一魔法。它只会添加一个不必要的定义层,但是,你得到的答案是,发现正在发生虚拟更新…很酷。我更新了我的响应,使人们更容易找到它这一评论。
$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
");