我正在使用PHP PDO,我遇到以下问题:
Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in /var/www/site/classes/enterprise.php on line 63
这是我的代码:
public function getCompaniesByCity(City $city, $options = null) {
$database = Connection::getConnection();
if(empty($options)) {
$statement = $database->prepare("SELECT * FROM `empresas` WHERE `empresas`.`cidades_codigo` = ?");
$statement->bindValue(1, $city->getId());
}
else {
$sql = "SELECT * FROM `empresas`
INNER JOIN `prods_empresas` ON `prods_empresas`.`empresas_codigo` = `empresas`.`codigo` WHERE ";
foreach($options as $option) {
$sql .= '`prods_empresas`.`produtos_codigo` = ? OR ';
}
$sql = substr($sql, 0, -4);
$sql .= ' AND `empresas`.`cidades_codigo` = ?';
$statement = $database->prepare($sql);
echo $sql;
foreach($options as $i => $option) {
$statement->bindValue($i + 1, $option->getId());
}
$statement->bindValue(count($options), $city->getId());
}
$statement->execute();
$objects = $statement->fetchAll(PDO::FETCH_OBJ);
$companies = array();
if(!empty($objects)) {
foreach($objects as $object) {
$data = array(
'id' => $object->codigo,
'name' => $object->nome,
'link' => $object->link,
'email' => $object->email,
'details' => $object->detalhes,
'logo' => $object->logo
);
$enterprise = new Enterprise($data);
array_push($companies, $enterprise);
}
return $companies;
}
}
答案 0 :(得分:2)
看起来你正在尝试建立一个长的(?)系列'或'比较:if (x=1) or (x=2) or (x=3) etc...
。您可能会发现更容易替换它:
$cnt = count($options);
if ($cnt > 0) {
$placeholders = str_repeat(', ?', $cnt - 1);
$sql .= 'WHERE '`prods_empresas`.`produtos_codigo` IN (?' . $placeholders . ')';
}
如果有5个选项,那么会给你
WHERE prods_empresas.produtos_condigo IN (?, ?, ?, ?, ?)
然后将值绑定到:
$pos = 1;
foreach ($options as $option) {
$statement->bindValue($pos, $option->getId());
$pos++
}
答案 1 :(得分:2)
绑定参数的数量与SQL中的绑定数量不匹配。仔细检查?
的数量和绑定参数的数量是否相同。
此外,如果您尝试绑定不存在的参数,则会显示HY093
:
$stmt = "INSERT INTO table VALUES (:some_value)";
$stmt->bindValue(':someValue', $someValue, PDO::PARAM_STR);
看到:some_value
与:someValue
不匹配!修复是:
$stmt = "INSERT INTO table VALUES (:some_value)";
$stmt->bindValue(':some_value', $someValue, PDO::PARAM_STR);
答案 2 :(得分:0)
SQL中的位置参数从1开始。您通过绑定到$ options循环中的位置$i+1
来处理它。
但是你将cidades_codigo
的最后一个参数绑定到位置count($options)
,这会覆盖$ options循环中的最后一个参数集。
您需要将最后一个参数绑定到位置count($options)+1
。
FWIW,您根本不需要bindValue()
。将参数数组传递给execute()
会更容易。以下是我写这个函数的方法:
public function getCompaniesByCity(City $city, $options = null) {
$database = Connection::getConnection();
$sql = "SELECT * FROM `empresas` WHERE `empresas`.`cidades_codigo` = ?"
$params = array();
$params[] = $city->getId();
if ($options) {
$sql .= " AND `prods_empresas`.`produtos_codigo` IN ("
. join(",", array_fill(1, count($options), "?") . ")";
foreach ((array)$options as $option) {
$params[] = $option->getId();
}
}
$statement = $database->prepare($sql);
echo $sql;
$statement->execute($params);
. . .
另外请务必检查prepare()
和execute()
的返回值,如果出现错误,它将为false
,您需要检查并报告错误。或者启用PDO以在错误时抛出异常。
答案 3 :(得分:0)
由于在传递给PDO :: Statement-> execute()
的命名参数映射数组中有额外的条目,我遇到了这个问题$args=array (":x" => 17 );
$pdo->prepare("insert into foo (x) values (:x)");
$pdo->execute($args); // success
$args[':irrelevant']=23;
$pdo->execute($args) // throws exception with HY093
答案 4 :(得分:-3)
由于您已在循环中设置了$i+1
,因此count($options)
将等于最后$i+1
,从而产生重复绑定。尝试
foreach($options as $i => $option)
{
$statement->bindValue($i + 1, $option->getId());
}
$statement->bindValue(count($options)+1, $city->getId());