PHP PDOException:"SQLSTATE [HY093]:参数号无效"

vij*_*rox 24 php mysql pdo

我尝试运行以下函数时收到错误"SQLSTATE [HY093]:参数号无效":

function add_persist($db, $user_id) {
    $hash = md5("per11".$user_id."sist11".time());
    $future = time()+(60*60*24*14);
    $sql = "INSERT INTO persist (user_id, hash, expire) VALUES (:user_id, :hash, :expire) ON DUPLICATE KEY UPDATE hash=:hash";
    $stm = $db->prepare($sql);
    $stm->execute(array(":user_id" => $user_id, ":hash" => $hash, ":expire" => $future));
    return $hash;
}
Run Code Online (Sandbox Code Playgroud)

我觉得这很简单,我只是没有抓住.有任何想法吗?

vee*_*vee 39

尝试:

$sql = "INSERT INTO persist (user_id, hash, expire) VALUES (:user_id, :hash, :expire) ON DUPLICATE KEY UPDATE hash=:hash2";
Run Code Online (Sandbox Code Playgroud)

$stm->execute(array(":user_id" => $user_id, ":hash" => $hash, ":expire" => $future, ":hash2" => $hash));
Run Code Online (Sandbox Code Playgroud)

摘自文档(http://php.net/manual/en/pdo.prepare.php):

调用PDOStatement :: execute()时,必须为要传递给语句的每个值包含唯一的参数标记.您不能在预准备语句中两次使用同名的命名参数标记.您不能将多个值绑定到单个命名参数,例如,SQL语句的IN()子句.


Ach*_*ome 15

这是使用PDO的一个限制.PDO只是确认查询和执行中的参数数量,并在任何不匹配时抛出错误.如果您需要在查询中使用参数重复,则必须使用变通方法来解决此问题

$sql = "insert into persist(user_id, hash, expire) values
    (:user_id, :hash, :value) on duplicate key update
    hash = :hash2";
$stm->execute(array(':user_id' => $user_id, ':hash' => $hash, ':hash2' => $hash,
    ':expire' => $expire));
Run Code Online (Sandbox Code Playgroud)

您可以参考此更详细的解决方法 - /sf/answers/532285631/

  • 惊人的!我花了两天时间调试除了一个特定查询之外的所有其他内容的代码。答案是(如上面的“vijrox”在评论中提到的)您不能在 PDO 中重用相同的命名参数。我有`UPDATE users SET username = :username, caption = :caption WHERE username = :username`,这不起作用,因为`:username` 出现了两次。修复是重命名第二个,最后是:`UPDATE users SET username = :username, caption = :caption WHERE username = :user`(最后一个`:user` 不同)。 (2认同)

Dun*_*can 5

我知道这是一个老问题,但我认为值得注意的是,更合适的解决方案是通过适当利用 SQL 来避免 PHP 中笨重的解决方法:

INSERT INTO `persist` (`user_id`, `hash`, `expire`)
VALUES (:user_id, :hash, :expire)
ON DUPLICATE KEY UPDATE `hash`=VALUES(`hash`)
Run Code Online (Sandbox Code Playgroud)

这样,您只需发送一次该值。