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

执行多个准备好的查询更新的PHP代码在第二次迭代中失败,出现重复键错误,php,mysql,prepared-statement,duplicates,Php,Mysql,Prepared Statement,Duplicates,我有一个框架来处理一组在第二次迭代中一直失败的简单(单表)更新查询。在我的框架内,我基于键值(col数据)对的关联数组构建了一个准备好的更新查询 我遇到的问题如下: foreach ($data as $row) call update($row); // pseudo code 框架为每一行构建(准备好的)更新查询,并返回操作的状态 第一个查询始终执行并成功更新,但对该方法的第二个查询始终返回错误: 键{key}的重复项{value} 最初,我有一个表的复合pkey,其中cols B、C、

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

我遇到的问题如下:

foreach ($data as $row) call update($row);  // pseudo code
框架为每一行构建(准备好的)更新查询,并返回操作的状态

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

键{key}的重复项{value}

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

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

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

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 = ?
$dblink->next_result()

在生成第二条语句之前

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

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

因此,显然,删除复合主键对mysql没有任何影响

我还尝试在每次迭代中生成(隔离)db链接资源,但得到了相同的结果

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

谢谢

--迈克

更新:2014年12月23日:

我很犹豫是否要显示bind/prepare的所有代码——在生成和准备查询时需要用到很多代码。从应用程序的跟踪记录中我知道,使用这种方法生成的查询总是成功的——直到我尝试提交连续的查询——该框架已经投入生产一年多了

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

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

第一个查询exec成功-所有后续查询的语法都正确(代码相同),但由于前面描述的错误而失败

我认为这个问题是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、hash和key列的组合。我删除了索引y'day,以消除复合键的复杂性,从而帮助诊断。从转储文件中可以看到,我现在只处理常规键

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

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\u cfg是
非空的自动增量
。您不应该试图在INSERT语句中设置它。省去它,让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 = ?

tl;问题出在代码中

索引问题无关紧要……复合键、id等

我没有解析输入元组,而是从类成员获取pkey信息,如果没有传递索引,该类成员(在代码中)默认为第0个元组。。。。这不是b/c,受影响的代码是第一代代码,从未考虑数据成员中的n元组

一旦我重构了核心代码来处理n元组,所有的工作都很顺利


感谢您提出的所有意见和建议,这让我开始寻找正确的位置。

这可能比任何需要修改索引的内容更无害。请在循环中发布用于准备、绑定和执行的代码,因为其中很容易出现小逻辑问题。此外,请发布来自
SHOW CREATE TABLE config_cfg
的输出,以便我们可以看到当前所有现有索引的结构。复合主键一开始看起来不错,但会导致撤消复杂性。因此,更新表格集值='foo'其中id=1vs
update table set value='foo'其中col_a=1和col_b=2
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 = ?