用于执行多个准备好的查询更新的 PHP 代码在第二次迭代时失败并出现重复键错误

标签 php mysql prepared-statement duplicates

我有一个处理一组简单(单表)更新查询的框架,这些查询在第二次迭代中始终失败。在我的框架内,我基于键值(col-data)对的关联数组构建了一个准备好的 UPDATE 查询。

我遇到的问题如下:

foreach ($data as $row) call update($row);  // pseudo code

框架为每行构建(准备好的)更新查询并返回操作的状态/状态。

第一个查询始终执行并成功更新,但对该方法的第二个查询始终返回错误:

键 {key} 的条目 {value} 重复

最初,我有一个表的复合 pkey,其中列 B、C、D 是主键。我尝试删除复合键进行测试,但它在 auto-inc 字段上生成错误,该字段被标记为“唯一”(不是主要的)。

在调试器中跟踪执行,我看到prepare() 成功的地方,但第二个查询在execute() 上失败,生成上述错误。

此外,在跟踪过程中,我确保遇到了以下语句:

$dblink->next_result();

在构建第二条语句之前。

Mysql 日志显示准备好的语句(第二个失败语句与第一个语句相同):

UPDATE /* /home/sn-m-beds/classes/MBEDS_mySQL.class.inc:(1982) */ config_cfg SET id_cfg = ?, ent_cfg = ?, hash_cfg = ?, key_cfg = ?, value_cfg = ?, modified_cfg = NOW() WHERE idHash_cfg = ?

$result 的内容(来自 $result->execute())是:

affected_rows = -1
insert_id = 0
num_rows = 0
param_count = 6
field_count = 0
errno = 1062
error = "Duplicate entry '31' for key 'id_cfg'"
error_list = {array}  (as above)
sqlstate = "23000"
id = 9

所以,显然,删除复合主键对于 mysql 来说没有任何影响。

我还尝试在每次迭代中生成(隔离)数据库链接资源,但提供了相同的结果。

不知道我还能看什么...任何建议或想法将不胜感激。

谢谢!

--迈克

更新:2014 年 12 月 23 日:

我不太愿意显示绑定(bind)/准备的所有代码 - 生成和准备查询涉及很多代码。我从应用程序的跟踪记录中知道,使用此方法生成的查询总是成功的 - 直到我尝试提交连续的查询 - 该框架已经投入生产一年多了。

我不认为问题出在正在执行的查询中——where子句判别限定符是针对唯一键(idHash_cfg)执行的——在调用这个核心成员函数之前,数据元组是评估,如果 idHash 键存在,则调用 update() 的数据库元组的方法,其中 no-idHash 值生成对构建插入命令的方法的调用。对于这两种情况,$data[] 元组作为参数之一传递给方法。

一些澄清 - 在框架内,每个类实例化都有一个名为 $data 的 protected 成员,它可以是元组数组。查询构建器为 $data 关联数组中的每一行构建、准备和执​​行查询。

第一个查询执行成功 - 所有后续查询都在语法上正确构建(相同的代码),但失败并出现前面描述的错误。

我认为这个问题是mysqli的db-link资源之一; MySQL 内部的某些内容(引用或资源或您想要调用的 w/e)正在阻止后续查询的成功执行。

这是表创建 SQL:

*************************** 1. row ***************************
   Table: config_cfg
Create Table: CREATE TABLE `config_cfg` (
  `id_cfg` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'pkey',
  `ent_cfg` char(3) NOT NULL COMMENT 'TLA for entity type',
  `hash_cfg` char(32) NOT NULL COMMENT 'hash key for the entity',
  `key_cfg` varchar(32) NOT NULL COMMENT 'configuration key value name',
  `value_cfg` varchar(32) NOT NULL COMMENT 'value assigned to the key',
  `created_cfg` datetime DEFAULT NULL,
  `createdBy_cfg` char(32) DEFAULT NULL,
  `accessed_cfg` datetime DEFAULT NULL,
  `modified_cfg` datetime DEFAULT NULL,
  `status_cfg` varchar(50) DEFAULT 'ACTIVE',
  `sessionIP_cfg` char(15) DEFAULT NULL,
  `idHash_cfg` char(32) DEFAULT NULL,
  UNIQUE KEY `id_cfg` (`id_cfg`),
  UNIQUE KEY `idHash_cfg` (`idHash_cfg`),
  KEY `status_cfg` (`status_cfg`),
  KEY `ent_cfg` (`ent_cfg`),
  KEY `hash_cfg` (`hash_cfg`),
  KEY `key_cfg` (`key_cfg`),
  CONSTRAINT `config_cfg_ibfk_1` FOREIGN KEY (`status_cfg`) REFERENCES `status_sts` (`name_sts`)
) ENGINE=InnoDB AUTO_INCREMENT=39 DEFAULT CHARSET=latin1 COMMENT='container for entity configuration settings/values'
1 row in set (0.00 sec)

所以,最初,我有一个复合索引作为主键 - ent、散列和键列的组合。我删除了该索引,以消除复合键的复杂性以帮助诊断。正如您从转储中看到的,我此时只处理常规 key 。

正在执行查询的一些代码片段:

if ($result = $dbLink->prepare($this->strQuery)) {
if (call_user_func_array(array($result, 'bind_param'), $bp->refValues($bp->get()))) {
    if ($result->execute()) {
        // [ snip... ]
    } else {  // where error reports are coming from
        snsError::set(ERROR_FATAL, 'query execution failure');
        snsError::set(ERROR_FATAL, $this->strQuery);
        snsError::set(ERROR_FATAL, $result->error);
        $success = false;
        $this->state = DATA_STATUS_MYSQL_ERROR;
    }

最佳答案

id_cfg 是非空自动增量。您根本不应该尝试在 INSERT 语句中设置它。不用管它,让 mysql 帮你填吧!将其从语句和绑定(bind)到占位符的值数组中删除。

UPDATE /* /home/sn-m-beds/classes/MBEDS_mySQL.class.inc:(1982) */ config_cfg 
SET id_cfg = ?, ent_cfg = ?, hash_cfg = ?, key_cfg = ?, value_cfg = ?, modified_cfg = NOW() 
WHERE idHash_cfg = ?

关于用于执行多个准备好的查询更新的 PHP 代码在第二次迭代时失败并出现重复键错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27613052/

相关文章:

php - 仅在每次注销时将 time_out 字段更新为数据库中最后插入的用户 ID?

php - 如何处理 PHP 中 FluentPDO 的安全问题?

php - unserialize() 函数不适用于新服务器上 MySQL 表中的变量

php - MYSQL - 使用 Group BY 获取当前项目的巨大问题

php - 循环遍历表单以更新 SQL 数据库

php - 一段时间后隐藏项目 [PHP/MySQL]

PHP通过多个表的搜索功能

mysql - Group By 来查找 SQL 中表元素之间的差异?

php - PDO 自定义类和安全性

java - 特殊字符和 preparedStatement 的问题,仅当我使用 setString 时