简体   繁体   English

HY093在PDO中执行准备好的语句时出错

[英]HY093 Error when executing prepared statement in PDO

I'm getting data from multiple API requests and storing each in a separate MySQL table. 我收到来自多个API请求数据,并存储在每一个单独的MySQL表。 For each request I have an associated table, with field names matching the JSON API response. 对于每个请求我具有相关联的表,其中相匹配的JSON API响应字段名称。 Since I'm not using all of fields from the API, I'm finding the fields in the MySQL table and using that to create the prepared statement with PDO, then feeding the results array into that for execution. 因为我没有使用的所有字段从API,我发现在MySQL表中的字段并用它来创建PDO的准备语句,然后喂养结果阵列成执行。 Here's the function that accepts the statement and the results array: 下面是接受语句,并将结果阵列功能:

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;
}

The last three lines in the foreach loop are just for debugging. 最后三行在foreach循环中都只是进行调试。

This worked fine for my first request, but no records are inserted, and I receive HY093, for others. 对于我的第一个请求,此方法工作正常,但未插入任何记录,对于其他人,我收到HY093。

For the one that works, the prepared statement ($sql) comes out as 对于可行的,准备好的语句($ sql)如下所示

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

I'm finding unique fields first, so that's why agent_id isn't in the update statement. 我第一次发现独特的领域,所以这就是为什么AGENT_ID是不是在更新语句。 This inserts successfully, even though I'm not using all the fields. 这成功地插入,即使我没有使用所有字段。 Here's the output of the var_dump and errorInfo: 这是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] => )

Now here's an example of one that doesn't work: 现在,这是一个不起作用的示例:

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

And part of the first API 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] => )

You can see I haven't included all 79 of the fields, but I've tried to include at least the fields with "name" in the label, and an empty string and a null value. 你可以看到我已经不包含字段的所有79,但我已经尽力至少包括与标签“名”,和一个空字符串和空值的字段。 Nothing but "name" and "record" should be bound, so I don't see those as a problem. 不过是“名”和“记录”应该被约束,所以我不认为那些是一个问题。

Every instance I've found online for this error code was due to a type (or case sensitivity). 我在网上找到了这个错误代码的每个实例是由于A型(或区分大小写)。 I've tried defining "record" as an int and a varchar. 我试图定义“记录”作为一个int和一个varchar。

Well, I had hoped that the process of typing this out would expose the problem to me, but no such luck. 好吧,我曾希望键入此内容的过程能使我明白问题所在,但没有这种运气。 If a night's sleep doesn't help, I'd love to hear thoughts. 如果一夜的睡眠无济于事,我很想听听想法。

Edit: Something else I have tried is removing the ON DUPLICATE UPDATE section (and emptied the table so there will not be any duplicates) so that each parameter is only bound once. 编辑:什么我都试过被去除对重复更新部分(和清空表,所以不会有任何重复),这样每个参数只能绑定一次。 It sounds like that was a bug a few years ago that has been fixes, but even without that I receive the same error. 听起来这是几年前的一个错误,现已修复,但即使没有该错误,我也会收到相同的错误。

Edit2: Hmm, even stranger, removing the ON DUPLICATE UPDATE causes some of my previously working statements to fail with the same error. EDIT2:嗯,甚至陌生人,去除对重复更新会导致一些自己以前的工作报表的失败,同样的错误。 Not all of them, and of course those that don't fail for that reason will fail if it runs into a duplicate. 并非所有这些都可以,当然,并非所有原因都不会失败的应用程序,如果遇到重复的操作,将失败。

Edit3: Something else I have tried is removing the binding-by-key for the update statement, and changing this to Edit3:我尝试过的其他方法是删除update语句的key-by-key,并将其更改为

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

I didn't think that would fix it, because it succeeds the first way on other tables, and this does in fact still fail. 我认为这不会解决它,因为它在其他表上成功了,但实际上仍然失败。

Edit4: I was able to make one of these work by adding fields to the MySQL table so that all the columns from the input array were being used. Edit4:我能够使所有正在使用的从输入数组列已添加到MySQL表中的字段,以使这些工作之一。 However, I don't think that's what really solved the problem, because I have others succeeding without all columns being used, even in the middle of the array. 不过,我不认为这是真正解决了这个问题,因为我有其他人没有被使用的所有列得手,甚至在阵列的中间。

Ok, I figured it out. 好的,我知道了。 First, I was not setting ATTR_EMULATE_PREPARES at all, which means it would default to the database preparation engine unless the PDO engine was required. 首先,我根本没有设置ATTR_EMULATE_PREPARES,这意味着它将默认为数据库准备引擎,除非需要PDO引擎。 Since MySQL cannot re-use placeholders, it was using the PDO engine. 由于MySQL无法重新使用占位符,因此它正在使用PDO引擎。 Setting that to false would force the MySQL engine, and all requests would fail. 将其设置为false将强制使用MySQL引擎,并且所有请求都将失败。

So the PDO engine can re-use placeholders, but however that happens it's not very good at finding the values. 因此,PDO引擎可以重用占位符,但是这种情况并不十分适合查找值。 Even trying to find 2 out of 3 columns it would sometimes fail. 即使试图从3列中找到2列,有时也会失败。 So rather than let PDO sort it out, I'm throwing out everything I don't need before I send it to be inserted. 因此,与其让PDO进行排序,不如将所有不需要的东西都扔掉,然后再将其插入。

I'm using a function to delete columns that I found 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>";

?>

This assumes that the first record will have an entry for every column. 假定第一条记录的每一列都有一个条目。 I do have some where that's not true, but so far it hasn't caused problems, but I will probably end up rewriting this to go through each row. 我确实有一些不正确的地方,但到目前为止还没有引起问题,但是我可能最终会重写它以遍历每一行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM