【问题标题】:Invalid parameter number on PDO Prepared StatementPDO Prepared Statement 上的参数号无效
【发布时间】:2011-01-07 11:33:04
【问题描述】:

我正在处理使用 PDO 类创建的一系列查询,在某些情况下,我的查询需要相同的参数。 我创建了一个用于保存数据的 foreach 语句中的数组,但一些变量来自外部,我可以在一个查询中使用这两个数据吗?

例子:

// $connection is the PDO object;
// $full_data contains:
// $full_data[$i]["address"]
// $full_data[$i]["phone"]
// $full_data[$i]["email"]
// $full_data[$i]["user_id"]
// $full_data[$i]["surname"] // not used but present
// $full_data[$i]["name"] // not used but present

$sql = "UPDATE users_table SET city = :address, phone = :phone, email = :email, admin_id = :admin_id, admin_name = :admin_name WHERE user_id = :user_id";
$statement = $connection->prepare ($sql);


$statement->bindParam (':admin_id', trim($admin_id), PDO::PARAM_INT);
$statement->bindParam (':admin_name', trim($admin_name), PDO::PARAM_STR);


foreach ($full_data as $value) {
    $ok = $statement->execute ($value);
    $num = $statement->rowCount ();
}

} catch (PDOException $e) {
    return $e->getMessage ();
}

此页面返回错误: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens

究竟是什么问题,在 UPDATE 语句中该技术有效

【问题讨论】:

    标签: php mysql exception pdo


    【解决方案1】:

    该死,我在几个小时后发现了问题......

    // $connection is the PDO object;
    // $full_data contains:
    // $full_data[$i]["address"]
    // $full_data[$i]["phone"]
    // $full_data[$i]["email"]
    // $full_data[$i]["user_id"]
    // ==> $full_data[$i]["surname"] // not used but present
    // ==> $full_data[$i]["name"] // not used but present
    

    查询["surname"]["name"]中未保存的数组数据产生错误。 execute (); 似乎需要精确的数组数据结构。 我已经用这个解决了这个问题:

    $sql = "UPDATE users_table SET city = :address, phone = :phone, email = :email, admin_id = :admin_id, admin_name = :admin_name WHERE user_id = :user_id";
    $statement = $connection->prepare ($sql);
    
    // must be removed ==> $statement->bindParam (':admin_id', trim($admin_id), PDO::PARAM_INT);
    // must be removed ==> $statement->bindParam (':admin_name', trim($admin_name), PDO::PARAM_STR);
    
    for ($i = 0; $i < count($full_data); $i++) {
        $full_data[$i]["admin_name"] = "the admin name";
        $full_data[$i]["admin_id"] = "100";
        unset ($full_data[$i]["surname"]); // IMPORTANT: must remove the unused vars
        unset ($full_data[$i]["name"]); // IMPORTANT: must remove the unused vars
    }
    
    
    
    foreach ($full_data as $value) {
        // bindParam can be avoided, but it's recommended for data type security
        $statement->bindParam(':address', trim($value['address']), PDO::PARAM_STR);
        $statement->bindParam(':phone', trim($value['phone']), PDO::PARAM_STR);
        $statement->bindParam(':email', trim($value['email']), PDO::PARAM_STR);
        $statement->bindParam(':admin_id', trim($value['admin_id']), PDO::PARAM_INT);
        $statement->bindParam(':admin_name', trim($value['admin_name']), PDO::PARAM_STR);
    
        $ok = $statement->execute ($value);
        $num = $statement->rowCount ();
    }
    
    } catch (PDOException $e) {
        return $e->getMessage ();
    }
    

    【讨论】:

      【解决方案2】:

      你需要绑定:address、:phone和:email参数。

      【讨论】:

      • 对不起,你能帮我多一点吗?这个解释没有,我用这个例子亲自测试过,如果它是数组形式,我可以避免绑定数据:stackoverflow.com/questions/2066320/…"
      • 在这种情况下,我认为您不需要使用 bindparam,而是在调用 foreach 之前将 :admin_id 和 :admin_name 添加到您的数组中。
      【解决方案3】:

      要详细说明BD answer,您缺少以下代码行:

      $statement->bindParam (':address', trim($address), PDO::PARAM_STR);
      $statement->bindParam (':phone', trim($phone), PDO::PARAM_STR);
      $statement->bindParam (':email', trim($email), PDO::PARAM_STR);
      

      另外,您的 foreach 循环似乎有问题,我认为这就是您想要的:

      $sql = "UPDATE users_table SET city = :address, phone = :phone, email = :email, admin_id = :admin_id, admin_name = :admin_name";
      $statement = $connection->prepare($sql);
      
      $statement->bindParam(':admin_id', trim($admin_id), PDO::PARAM_INT);
      $statement->bindParam(':admin_name', trim($admin_name), PDO::PARAM_STR);
      
      foreach ($full_data as $value)
      {
          $statement->bindParam(':address', trim($value['address']), PDO::PARAM_STR);
          $statement->bindParam(':phone', trim($value['phone']), PDO::PARAM_STR);
          $statement->bindParam(':email', trim($value['email']), PDO::PARAM_STR);
      
          $ok = $statement->execute();
          $num = $statement->rowCount();
      }
      

      【讨论】:

      • 我还是有问题,我在 foreach 循环中没有使用 bindParam 就完成了其他查询,如此处所述,它可以工作 php.net/manual/en/pdostatement.execute.php#71929
      • @Vittorio Vittori:我的代码中有错字,再试一次。关于 PHP.net 上的评论,我不会遵循该建议,它可能会导致代码中出现一些晦涩的错误。但我想这不起作用的原因是因为您不能将 bindParam()execute() 与附加参数一起使用 - 我不确定这一点,但它有点道理。
      • @Vittorio Vittori:您可以尝试将$admin_id$admin_name 添加到$_POST 数组中,如果您真的想避免调用bindParam()...您只需要这样做$statement-&gt;execute($values) 在 foreach 循环中。
      • 感谢您的指导,他们对我找到问题很重要
      • 我已经按照我的答案更正中的说明解决了这个问题,但是当您说“您的 foreach 循环似乎有问题”时,您的帮助很重要。我没想到这是一个数组大小问题,未使用的 vars "name" 和 "surname" 是主要问题
      猜你喜欢
      • 2011-07-24
      • 1970-01-01
      • 2014-05-31
      • 1970-01-01
      • 1970-01-01
      • 2014-12-17
      • 2014-02-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多