PDO Insert 将值 1 写入具有绑定参数的所有字段

Posted

技术标签:

【中文标题】PDO Insert 将值 1 写入具有绑定参数的所有字段【英文标题】:PDO Insert writes value of 1 into all fields with bound parameters 【发布时间】:2014-05-31 15:58:34 【问题描述】:

我有一个包含以下字段/数据类型的联系人表:contactid(PK,自动递增,不为空)、fname varchar(50)lname varchar(50)email varchar(50)is_member tinyint(1)(即布尔值) 和createdate date

数据被提交到表单所在的同一个php页面,$_POST数组的值被打包成一个Contact对象并传递给如下函数:

<?php
    public static function insertContact(Model $model, Contact $contact) 
        $database = new Database();
        $sql = 'INSERT INTO contact (fname, lname, email, is_member, createdate) VALUES (:fname, :lname, :email, :is_member, CURDATE())';
        $params = array(
            ':fname' => $contact->getFirstname(),
            ':lname' => $contact->getLastname(),
            ':email' => $contact->getEmail(),
            ':is_member' => intval($contact->isMember())
        );
        $result = $database->query($sql, $params, 'LASTID'); // Will return last inserted ID.
        $model->notify('Added contact ID ' . strval($result) . ' to the database.');
    
?>

如果另一个检查联系人是否已存在的函数返回false,则调用此函数。我正在使用 PDO 准备好的语句,对于 SELECT 语句来说一切正常,但是当我尝试执行这个 INSERT 语句时,我遇到了问题。 $params 数组是正确的,并且参数的数量与占位符的数量相匹配,但是 is_member 字段会导致问题。如果值为1,则INSERT 完成,但结果行如下所示:

contactid fname lname email is_member createdate 14 1 1 1 1 2014-05-31

以前有人见过这种行为吗?此外,如果is_member 的值为0,则查询将完全失败,并出现PDOStatement 警告[HY093]: Invalid parameter number: number of bound variables does not match number of tokens。我没有得到的是 $params 具有正确数量的值来绑定到占位符标记。

[更新:]$database-&gt;query()方法如下:

<?php
    // Return type is the format in which to return the result of the query.
    public function query($sql, $params, $returnType) 
        if($stmt = $this->connection->prepare($sql)) 
            foreach($params as $key => $value) 
                if($value != 'noParams') 
                    $stmt->bindParam($key, $value);
                
            
            if($stmt->execute())     // execute() returns TRUE on success
                 switch($returnType) 
                     case 'ASSOC':
                         $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
                     break;
                     case 'LASTID':
                         $result = $this->connection->lastInsertId();
                     break;
                     // ... more cases, etc.
                 
              else 
                 $result = null;
                 die('Error: ' . $this->connection->error);
             

             return $result;
          else 
             die('Prepare failed: (' . $this->connection->error . ')');
         
     
?>

如前所述,此query() 方法适用于为SELECT 操作准备的语句,但是当尝试执行简单的INSERT 时,它会表现出上述行为。任何帮助表示赞赏!谢谢!

【问题讨论】:

以前没有人见过这种行为。 我更想问$database->query()函数是做什么的。 显示$database-&gt;query() 方法的代码 @MarkBaker,我已更新帖子以包含$database-&gt;query() 的代码。我了解到这是用于 PDO 准备语句的一种相当常见的方法,并且使用命名占位符比使用位置 ? 标记更直接。 【参考方案1】:

第一个问题:

if($value != 'noParams') 

如果值为 0,那么这将是一个错误匹配,因为它是一个 松散类型 比较;所以“假”类型值(null0.0false 等)会给你带来问题,因为它不会绑定数组中的任何假值......这解释了你的 Invalid parameter number: number of bound variables does not match number of tokens 错误。 ..

严格比较:

if($value !== 'noParams') 

你的第二个问题:

引用PHP Docs

与 PDOStatement::bindValue() 不同,该变量被绑定为引用,并且只会在调用 PDOStatement::execute() 时进行评估。

在您实际执行语句时,$value 仅具有来自绑定循环的最后一次迭代的值,即来自is_member 数组元素的值,即1。这就是为什么您的所有绑定变量除了 1 值之外什么都没有得到

将您的 foreach 循环更改为

foreach($params as $key => &$value) 

所以$value 是“通过引用”,它应该是绑定到每个绑定变量的正确引用

或者,使用bindValue() 而不是bindParam()

整体:

所以为了彻底修复

foreach($params as $key => &$value) 
    if($value !== 'noParams') 
        $stmt->bindParam($key, $value);
    

【讨论】:

啊,是的,效果很好!不敢相信我错过了它没有绑定参考。非常感谢!【参考方案2】:

您是否尝试过使用 exec 与查询?

在文档中: http://us1.php.net/manual/en/pdo.exec.php

对比 http://us1.php.net/pdo.query

底线:PDO::query — 执行 SQL 语句,将结果集作为 PDOStatement 对象返回 while PDO::exec — 执行一条 SQL 语句并返回受影响的行数

【讨论】:

以上是关于PDO Insert 将值 1 写入具有绑定参数的所有字段的主要内容,如果未能解决你的问题,请参考以下文章

Pdo - 将值插入数据库错误 SQLSTATE [HY093] [重复]

将值和数组添加到 PDO 执行方法

在 PDO 中的执行函数中将 NULL 值绑定到具有关联数组的命名占位符的问题

SQL Server 错误 1934 发生在 INSERT 到具有计算列 PHP/PDO 的表中

数据库抽象层PDO 8

执行 pdo insert 排除某些参数