【问题标题】:HY093 Error when executing prepared statement in PDOHY093 在 PDO 中执行准备好的语句时出错
【发布时间】:2018-07-11 08:41:59
【问题描述】:

我从多个 API 请求中获取数据,并将每个请求存储在单独的 MySQL 表中。对于每个请求,我都有一个关联表,其字段名称与 JSON API 响应匹配。由于我没有使用 API 中的所有字段,因此我在 MySQL 表中查找字段并使用它来创建带有 PDO 的准备好的语句,然后将结果数组输入其中以供执行。下面是接受语句和结果数组的函数:

function insert_array($sql,$args)
{
    $this->connect();
    $q = $this->con->prepare($sql);
    foreach($args as $record) {
        $q ->execute($record);
        echo "<pre>";var_dump($record);echo "</pre>";
        $arr = $q->errorInfo();
        print_r($arr);
    }
    $this->disconnect();
    return $q;
}

foreach 循环中的最后三行仅用于调试。

这对我的第一个请求很好,但没有插入任何记录,我收到 HY093,其他人。

对于一个有效的,准备好的语句 ($sql) 输出为

INSERT INTO fs_dynamicagents (agent_id, firstname, lastname) VALUES (:agent_id, :firstname, :lastname) ON DUPLICATE KEY UPDATE firstname=:firstname, lastname=:lastname

我首先要查找唯一字段,这就是为什么 agent_id 不在更新语句中的原因。即使我没有使用所有字段,这也会成功插入。这是 var_dump 和 errorInfo 的输出:

array(4) {
  ["agent_id"]=>
  string(3) "002"
  ["firstname"]=>
  string(9) "Bill"
  ["lastname"]=>
  string(5) "Murray"
  ["password"]=>
  string(4) "1212"
}
Array ( [0] => 00000 [1] => [2] => )

下面是一个不起作用的例子:

INSERT INTO fs_queue (name, record) VALUES (:name, :record) ON DUPLICATE KEY UPDATE record=:record

以及第一条 API 记录的一部分:

array(79) {
  ["name"]=>
  string(7) "Choice1"
  ["fc_name"]=>
  string(7) "Choice1"
  ["friendlyname"]=>
  string(7) "Choice1"
  ["record"]=>
  string(1) "1"
  ["agent_announcement_file"]=>
  string(0) ""
  ["play_agent_announcement_file"]=>
  string(1) "0"
  ["incoming_call_script"]=>
  string(0) ""
  ["caller_agent_match"]=>
  string(1) "0"
  ["survey_id"]=>
  NULL
}

Array ( [0] => HY093 [1] => [2] => )

您可以看到我没有包含所有 79 个字段,但我尝试至少包含标签中带有“名称”的字段,以及一个空字符串和一个空值。应该绑定“名称”和“记录”,所以我不认为这些是问题。

我在网上找到的每个错误代码实例都是由类型(或区分大小写)引起的。我尝试将“记录”定义为 int 和 varchar。

嗯,我曾希望输入此内容的过程会将问题暴露给我,但没有这样的运气。如果一夜睡眠没有帮助,我很想听听想法。

编辑:我尝试过的其他方法是删除 ON DUPLICATE UPDATE 部分(并清空表,因此不会有任何重复),以便每个参数只绑定一次。听起来这是几年前的一个错误,已经修复,但即使没有,我也会收到同样的错误。

Edit2:嗯,更奇怪的是,删除 ON DUPLICATE UPDATE 会导致我以前的一些工作语句失败并出现相同的错误。不是所有的,当然那些没有因为这个原因而失败的人如果遇到重复也会失败。

Edit3:我尝试过的其他方法是删除更新语句的按键绑定,并将其更改为

INSERT INTO fs_queue (name, record) VALUES (:name, :record) ON DUPLICATE KEY UPDATE record= VALUES(record)

我认为这不会解决它,因为它在其他表上以第一种方式成功,而实际上这仍然失败。

Edit4:我能够通过向 MySQL 表添加字段来完成其中一项工作,以便使用输入数组中的所有列。但是,我认为这并不是真正解决问题的方法,因为我有其他人在没有使用所有列的情况下成功,即使在数组中间也是如此。

【问题讨论】:

  • 您是否尝试使用示例给定参数手动执行该查询?它会给你一个错误吗?
  • name 是唯一键吗?
  • 我确实测试了查询,但是这个错误是绑定参数失败,可能是由于缺少值或字段名称不匹配。它实际上从未到达执行点,但它确实成功插入了第一个查询。
  • 是的,名称是唯一的,这就是它被排除在更新语句之外的原因。
  • 有没有办法更详细地报告错误,特别是查看尝试绑定哪些字段和值?

标签: php mysql pdo


【解决方案1】:

好的,我想通了。首先,我根本没有设置 ATTR_EMULATE_PREPARES,这意味着除非需要 PDO 引擎,否则它将默认为数据库准备引擎。由于 MySQL 不能重用占位符,它使用的是 PDO 引擎。将其设置为 false 将强制 MySQL 引擎,并且所有请求都会失败。

因此 PDO 引擎可以重复使用占位符,但是发生这种情况时它并不擅长查找值。即使试图找到 3 列中的 2 列,它有时也会失败。因此,我没有让 PDO 对其进行整理,而是在发送插入之前丢弃所有我不需要的东西。

我正在使用一个函数来删除我找到的列 here

<?php

function delete_col(&$array, $key) {
    return array_walk($array, function (&$v) use ($key) {
        unset($v[$key]);
    });
}

$table_fields = array("id","fruit");

$insert_data = array(
    array( 
        "id" => "1",
        "fruit" => "Apple",
        "color" => "Red"
    ),array( 
        "id" => "2",
        "fruit" => "Apple",
        "color" => "Green"
    ),array( 
        "id" => "3",
        "fruit" => "Pear",
        "color" => "Green"
    )
);

foreach($insert_data[0] as $key=>$value) {
    if(!in_array($key, $table_fields)) {
        delete_col($insert_data, $key);
    }
}
echo "<pre>";
print_r($insert_data);
echo "</pre>";

?>

这假定第一条记录的每一列都有一个条目。我确实有一些不正确的地方,但到目前为止它还没有引起问题,但我可能最终会重写它以遍历每一行。

【讨论】:

    猜你喜欢
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-30
    • 1970-01-01
    相关资源
    最近更新 更多