下一个代码给我一个错误SQLSTATE[HY093]: Invalid parameter number
$sql = "INSERT INTO `users` (`id`, `date_install`, `date_ping`, `cc`, `uv`, `pid`, `pv`, `aff_id`, `sub_id`, `channel`, `cid`, `os`, `av`, `db`) VALUES (:id, :date_install, now(), :country, :updaterVersion, :productId, :productVersion, :affiliateId, :subId, :channel, :commandId, :os, :av, :defaultBrowser) "
. "ON DUPLICATE KEY UPDATE `date_install` = :date_install, `date_ping` = now(), `cc` = :country, `uv` = :updaterVersion, `pid` = :productId, `pv` = :productVersion, `aff_id` = :affiliateId, `sub_id` = :subId, `channel` = :channel, `cid` = :commandId, `os` = :os, `av` = :av, `db` = :defaultBrowser ";
$statement = $database->prepare($sql);
$statement->bindValue(":id", $user->id, PDO::PARAM_INT);
$statement->bindValue(":date_install", $user->date_install, PDO::PARAM_STR);
$statement->bindValue(":country", $user->cc, PDO::PARAM_STR);
$statement->bindValue(":updaterVersion", $user->uv, PDO::PARAM_INT);
$statement->bindValue(":productId", $user->pid, PDO::PARAM_INT);
$statement->bindValue(":productVersion", $user->pv, PDO::PARAM_INT);
$statement->bindValue(":affiliateId", $user->aff_id, PDO::PARAM_INT);
$statement->bindValue(":subId", $user->sub_id, PDO::PARAM_INT);
$statement->bindValue(":channel", $user->channel, PDO::PARAM_STR);
$statement->bindValue(":commandId", $user->cid, PDO::PARAM_INT);
$statement->bindValue(":os", $user->os, PDO::PARAM_STR);
$statement->bindValue(":av", $user->av, PDO::PARAM_STR);
$statement->bindValue(":defaultBrowser", $user->db, PDO::PARAM_STR);
$statement->execute();
我不知道出了什么问题,如果我将SQL复制/粘贴到控制台并手动替换所有值,一切正常。另外,如果我注释掉部分ON DUPLICATE KEY...
,也可以。
答案 0 :(得分:3)
如果您的PDO实例为emulation mode is turned off,则您无法在查询中多次使用相同的占位符名称。
此外,对于ON DUPLICATE,它也没有必要,因为你总是可以使用VALUES
运算符来获取VALUES子句中的值:
ON DUPLICATE KEY UPDATE `date_install` = VALUES(date_install), ...
答案 1 :(得分:1)
PDO不允许重复变量名称。你的ON DUPLICATE KEY UPDATE应该拥有它自己的变量名。这也意味着你必须分配你的变量2次。这是一个可悲的限制:(。
答案 2 :(得分:1)
为了使用相同的参数名称两次,您必须将PDO::ATTR_EMULATE_PREPARES
属性设置为true
:
$database->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);