php SQL状态[HY 093]:无效的参数编号:绑定变量数与标记数不匹配- FOREACH循环

bq3bfh9z  于 2022-11-28  发布在  PHP
关注(0)|答案(2)|浏览(187)

我是一个PHP新手,所以请对我宽容一点。
我收到此错误“SQLSTATE[HY 093]:无效参数...”。
我有一个函数,它有三个参数:$表格,$数据,$标识
其中$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循环相同。
我修改了代码,在每次绑定值时添加了一个计数器。计数器计数到16,这是预期的。这使得我用foreach循环绑定了16次值,第17次是手动完成的。
由于两个foreach循环都使用相同的数据集,我不知道为什么会出现这个错误。
EDIT:包含我的数据库类。

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

}

6yjfywim

6yjfywim1#

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

wz3gfoph

wz3gfoph2#

好了,我修好了。
问题出在$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');

我确实让它工作了,但我不知道为什么第一种方法不起作用。我会深入研究文档,试图找到答案。当我找到答案时,我会向你报告。

相关问题