简体   繁体   English

zend 框架:如何准备和执行 WHERE IN 子句?

[英]zend framework: how to prepare and execute WHERE IN clause?

I want to prepare a statement for use inside a loop.我想准备一个在循环内使用的语句。 When I try to execute the statement I see an error in the logs saying "Invalid parameter number: no parameters were bound'".当我尝试执行该语句时,我在日志中看到一条错误消息,显示“参数编号无效:未绑定参数”。

What's wrong with my code?我的代码有什么问题?

$itemSelectSql = "SELECT * FROM `tblItems` WHERE `itemID` IN (?)";
$itemSelectStmt = new Zend_Db_Statement_Mysqli($this->db_ro, $itemSelectSql);
while () {
  ...
  $itemIds = array();
  // populate $itemIds array
  ...
  $itemSelectStmt->execute(array($itemIds));
}

EDIT:编辑:

I think I may have a bug in my set up which explains why whatever I try fails.我想我的设置中可能有一个错误,这解释了为什么我尝试失败的原因。 I'm seeing this:我看到了这个:

PHP Warning:  call_user_func_array() expects parameter 1 to be a valid callback, 
class 'PDOStatement' does not have a method 'bind_param' in 
/var/www/lib/Zend/Db/Statement/Mysqli.php on line 204

EDIT:编辑:

I was using the wrong adapter.我使用了错误的适配器。 Should have been Zend_Db_Statement_Pdo:-)应该是 Zend_Db_Statement_Pdo :-)

Thanks for the replies.感谢您的回复。

? can't be replaced by an array, it has to be replaced by a scalar (thanks to comment for pointing out that this does not always mean string... brain-fart on my end).不能用数组替换,它必须用标量替换(感谢评论指出这并不总是意味着字符串......我的大脑放屁)。 Let me know if this works better:让我知道这是否效果更好:

$itemSelectSql = "SELECT * FROM `tblItems` WHERE `itemID` IN ";
while () {
  ...
  $itemIds = array();
  // populate $itemIds array
  ...
  // we need to have the same number of "?,"'s as there are items in the array.
  // and then remove final comma.
  $qs = rtrim(str_repeat("?,", count($itemIds)),',');
  // create a statement based on the result
  $itemSelectStmt = 
       new Zend_Db_Statement_Mysqli($this->db_ro, "$itemSelectSql ($qs)");
  // bind to each of those commas.
  $itemSelectStmt->execute($itemIds);
}

Have you tried doing this:您是否尝试过这样做:

while () {
  ...
  $itemIds = array();
  // populate $itemIds array
  $itemIds = implode(',' $itemIds);
  $itemSelectStmt->execute(array($itemIds));
}

I'm not an expert of Zend_framework, but when you use statements, to the execute method you must我不是 Zend_framework 的专家,但是当你使用语句时,你必须

If you use positional parameters, or those that are marked with a question mark symbol ('?'), pass the bind values in a plain array.如果您使用位置参数,或那些标有问号 ('?') 的参数,请将绑定值传递到普通数组中。

So i think you need to pass an array with one value and that value replace the "?"所以我认为你需要传递一个带有一个值的数组,并且该值替换“?” in the statement.在声明中。 In this case you need a comma separated string (if you ids are int) to replace (?) in the statement.在这种情况下,您需要一个逗号分隔的字符串(如果您的 id 是 int)来替换语句中的 (?)。

What you do if you do not implode the values is passing an array containing an array.如果您不内爆这些值,您所做的就是传递一个包含数组的数组。

You might use FIND_IN_SET(str,strlist) instead of IN () :您可以使用FIND_IN_SET(str,strlist)而不是IN ()

mysql> select id, name from customer where find_in_set(id, '10,15,20');
+----+---------+
| id | name    |
+----+---------+
| 10 | ten     |
| 15 | fifteen |
| 20 | twelve  |
+----+---------+

This way, you don't have to bind array with multiple values to IN() , you can pass list of IDs as a single comma-separated string.这样,您不必将具有多个值的数组绑定到IN() ,您可以将 ID 列表作为单个逗号分隔的字符串传递。 You can safely use PHP function implode() to generate string from array of IDs.您可以安全地使用 PHP function implode()从 ID 数组生成字符串。

Though, I'm not sure if it has any impact on performance.不过,我不确定它是否对性能有任何影响。 I took a look at output of explain , and it looks like find_in_set() is not able to use indexes, so generating queries with variable number of parameters should perform better.我查看了explain的 output ,看起来find_in_set()无法使用索引,因此生成具有可变数量参数的查询应该会更好。

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

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