我有一个处理一组简单(单表)更新查询的框架,这些查询在第二次迭代中始终失败。在我的框架内,我基于键值(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/