【问题标题】:Uncaught exception 'PDOException' with message 'SQLSTATE[HY093]: Invalid parameter number'带有消息“SQLSTATE [HY093]:无效参数号”的未捕获异常“PDOException”
【发布时间】:2016-09-07 11:44:36
【问题描述】:

每当我尝试使用 PDO 插入数据库时​​都会收到错误消息。

public function save($primaryKey = "") {
        $validate = $this->rules();
        if ($validate === true) {
            $properties = '';
            $values = '';
            $bindings = array();
            $update = '';
            foreach ($this as $property => $value){
                if ($property === "conn") {
                    continue;
                }
                $properties .= $property . ',';
                $values .= ':' . $property . ',';
                $update .= $property . ' = :' . $property . ',';
                $bindings[':'.$property] = $value;
            }
            $sql_string = 'INSERT INTO ' . get_class($this) . ' (' . rtrim($properties, ',') . ') ';
            $sql_string .= 'VALUES (' . rtrim($values, ',') . ') ON DUPLICATE KEY UPDATE ' . rtrim($update, ',') . ';';
            $result = $this->executeQuery(NULL, $sql_string, $bindings);
            $this->buildObject($result);
            if (!empty($primaryKey)) {
                $this->$primaryKey = $this->conn->lastInsertId();
            }
            return $result;
        } else {
            return $validate;
        }
    }

public function executeQuery($object, $sql_string, $bindings = null) {
        $stmt = $this->conn->prepare($sql_string);
        if (!empty($bindings)) {
            if (!$stmt->execute($bindings)) {return false;}
        } else {
            if (!$stmt->execute()) {return false;}
        }
        $result = (!empty($object) ? $stmt->fetchAll(PDO::FETCH_CLASS, $object) : $stmt->fetchAll());
        return (($stmt->rowCount() > 0) ? $result : false);
    }

save 函数生成查询字符串和看起来都正确的绑定。

query = INSERT INTO am_administrator (firstName,lastName,username,password,email,isSuperUser,dateCreated,dateLastModified) VALUES (:firstName,:lastName,:username,:password,:email,:isSuperUser,:dateCreated,:dateLastModified) ON DUPLICATE KEY UPDATE firstName = :firstName,lastName = :lastName,username = :username,password = :password,email = :email,isSuperUser = :isSuperUser,dateCreated = :dateCreated,dateLastModified = :dateLastModified;

bindings = array(8) { 
[":firstName"]=> string(5) "First" 
[":lastName"]=> string(4) "Last" 
[":username"]=> string(7) "cova-fl" 
[":password"]=> string(8) "password" 
[":email"]=> string(16) "test@testing.com" 
[":isSuperUser"]=> int(1) "1" 
[":dateCreated"]=> string(19) "2016-05-11 02:40:15" 
[":dateLastModified"]=> string(19) "2016-05-11 02:40:15" 
}

每当我将查询放入工作台时,我都没有问题,但是当尝试在代码中运行它时,我得到致命错误:未捕获的异常 'PDOException' 并带有消息 'SQLSTATE[HY093]: Invalid parameter number',这让我很困惑,因为绑定参数的数量与绑定键和数字匹配。任何人都可以在这个问题上启发我吗?

【问题讨论】:

  • 注意:通常最好先执行$values = [ ],然后附加到该数组,最后附加到implode($values, ','),而不是连接并去除多余的,
  • 在某些时候,您可能需要考虑使用像 DoctrinePropel 这样的 ORM,如果不是正确的 development framework,那么您最终会意外滚动自己。 Laravel 特别容易上手,并且已经可以满足您开箱即用的需求。
  • @tadman 注意,会做出改变。你会碰巧知道我的主要问题吗?由于存在限制,我在 ORM 上受到限制。所以我最终可能会建造一个既不好也不好玩的小...
  • 是的,我对你有感觉。使用现成的总是比自己动手更好的计划。与摸索并从头开始编写相比,学习如何使用它所花费的时间要少得多。你在这里做的事情已经足够紧张了,我希望你有单元测试来验证它是否正常工作。
  • 是的,单元测试是唯一让这一切变得可能的事情

标签: php mysql pdo


【解决方案1】:

我认为这可能是因为您在语句中对每个绑定进行了两次声明,例如:firstname 出现在 VALUES 子句以及 ON DUPLICATE KEY UPDATE 子句中。

您只将 8 个绑定传递给 $stmt->execute,但 PDO 正在寻找 16 个。

您可以尝试在 ON DUPLICATE KEY UPDATE 子句中命名它们略有不同,给您一个查询,例如,例如

INSERT INTO am_administrator (firstName,lastName,username,password,email,isSuperUser,dateCreated,dateLastModified) VALUES (:firstName,:lastName,:username,:password,:email,:isSuperUser,:dateCreated,:dateLastModified) ON DUPLICATE KEY UPDATE firstName = :update_firstName,lastName = :update_lastName,username = :update_username,password = :update_password,email = :update_email,isSuperUser = :update_isSuperUser,dateCreated = :update_dateCreated,dateLastModified = :update_dateLastModified;

【讨论】:

  • 非常感谢。我不知道绑定值不能在查询字符串中绑定参数的所有实例之间共享。
  • 为什么不直接使用VALUES 例如INSERT INTO table (firstName, lastName) VALUES (:firstName, :lastName) ON DUPLICATE KEY UPDATE firstName = VALUES(firstName), lastName = VALUES(lastName) ?这样你就不需要那么多占位符了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-06
  • 2017-04-26
相关资源
最近更新 更多