SQLSTATE[HY093]:参数编号无效:绑定变量的数量与令牌的数量不匹配-FOREACH循环



我是PHP的新手,所以请对我宽容一点。

我收到这个错误";SQLSTATE[HY093]:无效参数"当我准备SQL语句并绑定值时。

我有一个函数,它有三个参数:$table、$data、$id

其中$table只是要在数据库中更新的表。

$id是我试图更新的表中项目的id。

$data是一个关联数组,其中$data[$key]与数据库中的列名匹配。

public function update_database($table, $data, $id)
{
$sql_statement = "'UPDATE `" . $table . "` SET ";
foreach ($data as $key => $value) {
if ($key === array_key_last($data)) {
$sql_statement .= $key . " = :" . $key . " WHERE id = :id '";
} else {
$sql_statement .= $key . " = :" . $key . ", ";
}
}
$this->db->query($sql_statement);
foreach ($data as $key => $value) {
$this->db->bind(':' . $key, $data[$key]);
}
$this->db->bind(':id', $id);

if($this->db->execute()){
//it worked!
return true;
}else{
//something did not work
return false;
}

我认为这个错误只是告诉我我没有绑定正确数量的值。

在我的SQL语句中,我绑定了17个值。16用于关联数组中的每个项目。我在17号贴在声明的末尾。以下是使用第一个foreach循环生成的SQL语句:

string(594) "'UPDATE `clan-info-static` SET tag = :tag, name = :name, location_id = :location_id, location_name = :location_name, location_iscountry = :location_iscountry, location_countrycode = :location_countrycode, badgeUrls_small = :badgeUrls_small, badgeUrls_medium = :badgeUrls_medium, badgeUrls_large = :badgeUrls_large, requiredTrophies = :requiredTrophies, warFrequency = :warFrequency, isWarLogPublic = :isWarLogPublic, warLeague_id = :warLeague_id, warLeague_name = :warLeague_name, requiredVersusTrophies = :requiredVersusTrophies, requiredTownhallLevel = :requiredTownhallLevel WHERE id = :id '"

第二个foreach循环绑定SQL语句中所需的值。它使用与第一个foreach循环相同的数据集。

我修改了代码,添加了一个ticker,以便在每次绑定值时进行计数。股票代码计数为16,这是意料之中的事。这使得我有16次将值与foreach循环绑定,第17次是手动完成的。

由于两个foreach循环都使用相同的数据集,我不知道它为什么会给我这个错误。

编辑:包括我的数据库类。

class Database{
private $host = DB_HOST;
private $user = DB_USER;
private $pass = DB_PASS;
private $dbname = DB_NAME;
private $dbh;
private $stmt;
private $error;
public function __construct(){
$dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
);
try{
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
}catch(PDOException $e){
$this->error = $e->getMessage();
echo $this->error;

}
}

public function query($sql){
$this->stmt = $this->dbh->prepare($sql);
}
public function bind($param, $value, $type = null){
if(is_null($type)){
switch(true){
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;

}
}
$this->stmt->bindValue($param, $value, $type);
}

public function execute(){
return $this->stmt->execute();
}

}

try{
$update_str = "";
foreach ($data as $key => $value){ 
$update_str .= (strlen($update_str) ? ", ":" ").$key." = :".$key;
}
$data["pk"] = $id;
$sql_statement = "'UPDATE `".$table."` SET ".$update_str." where id = :pk";
$this->db->prepare($sql_statement)->execute($data);
return true;
}
catch(Exception $e){
// die($e->getMessage()); // get error message
return false;
}

将此包含在函数中,这是我在项目中通常要做的。请对输入的值进行消毒,以防止出现不愉快的事件。如果出现错误,您可以使用beginTransaction方法来处理rollBack

好的,我成功了。

问题出在$this->db->query($sql_statement);上。出于某种原因,它不喜欢我简单地传递预制语句。当我构建这样的语句时:$this->db->query('UPDATE ' . $table . ' SET ' . $items . ' WHERE id = :id');。它按预期工作。

我编辑了我的第一个foreach循环来获取项目,而不是构建整个语句:

旧:

$sql_statement = "'UPDATE `" . $table . "` SET ";
foreach ($data as $key => $value) {
if ($key === array_key_last($data)) {
$sql_statement .= $key . " = :" . $key . " WHERE id = :id '";
} else {
$sql_statement .= $key . " = :" . $key . ", ";
}
}
$this->db->query($sql_statement);

新增:

$items = "";
foreach ($data as $key => $value) {
if ($key === array_key_last($data)) {
$items .= $key . " = :" . $key;
} else {
$items .= $key . " = :" . $key . ", ";
}
}

$this->db->query('UPDATE `' . $table . '` SET ' . $items . ' WHERE id = :id');

我确实做到了,但我不确定为什么第一种方法不起作用。我将深入研究文档,并试图找到答案。我发现后会回来报告。

最新更新