【问题标题】:Executing Multiple Queries Using PDO使用 PDO 执行多个查询
【发布时间】:2016-11-01 11:50:11
【问题描述】:

我正在尝试使用 PDO 准备语句执行以下查询,但是当我调用 $query->fetch(); 时,它会引发异常 SQLSTATE[HY000]: General Error

这是 PHP 代码(注意类 Database - 或代码中的变量 $db - 只是类 PDO 的简单包装,因此所有 PDO 调用都必须使用 $db->pdo->{some PDO function}(); 完成):

$db = new Database(); //Create a new object of type Database establishing a connection to the MySQL database
$query = $db->pdo->prepare("INSERT INTO `orders` (`order_type`, `item`, `amount`, `price`, `price_btc`, `status`, `timestamp`, `placed_by`, `secret`, `first_name`, `last_name`, `address_1`, `address_2`, `city`, `zip_code`, `country`, `state`, `phone_number`)
                         VALUES(:order_type, :item, :amount, :price, :price_btc, :status, :timestamp, :placed_by, :secret, :first_name, :last_name, :address_1, :address_2, :city, :zip_code, :country, :state, :phone_number);
                         SELECT * FROM `orders` WHERE `ID`=LAST_INSERT_ID();"); //Prepare the two queries to be executed

/*HERE IS SOME CODE TO BIND PLACEHOLDERS TO SOME VALUES*/

if(!$query->execute()){
    error(); //Handle the error and terminate execution
}
if($query->rowCount() != 1){
    error(); //Handle the error and terminate execution
}

$query->setFetchMode(PDO::FETCH_ASSOC);
$order = $query->fetch(); //THIS IS WHERE THE EXCEPTION IS THROWN!

我尝试通过 PHPMyAdmin 手动执行查询,它运行良好。我还读到 PDO 不支持在同一语句中进行多个查询,但是在运行 $query->execute(); 时不应该抛出异常吗?

另外,$query->rowCount(); 确实返回 1,但是当我尝试获取结果时,它会引发一般错误异常。

我尝试了很多其他方法,例如将 SELECT 语句替换为 SELECT LAST_INSERT_ID();,但似乎没有任何效果。

感谢您的帮助!

【问题讨论】:

  • /*HERE IS SOME CODE TO BIND PLACEHOLDERS TO SOME VALUES*/ - 因此,将代码留给您认为不相关的绑定,或者您没有绑定这些代码?问题不清楚(对我来说)。或者,这个问题更像是“为什么会有这种行为”?
  • 为什么需要SELECT * FROM `orders` WHERE ID=LAST_INSERT_ID();?使用php.net/manual/en/pdo.lastinsertid.php

标签: php mysql pdo


【解决方案1】:

您不需要多重声明。

所以只需一个一个地运行您的查询

$db = new Database(); //Create a new object of type Database establishing a connection to the MySQL database
$query = $db->pdo->prepare("INSERT INTO `orders` (`order_type`, `item`, `amount`, `price`, `price_btc`, `status`, `timestamp`, `placed_by`, `secret`, `first_name`, `last_name`, `address_1`, `address_2`, `city`, `zip_code`, `country`, `state`, `phone_number`)
                         VALUES(:order_type, :item, :amount, :price, :price_btc, :status, :timestamp, :placed_by, :secret, :first_name, :last_name, :address_1, :address_2, :city, :zip_code, :country, :state, :phone_number)"
); //Prepare the first query

/*HERE IS SOME CODE TO BIND PLACEHOLDERS TO SOME VALUES*/

$query->execute();

$order = $db->pdo->query("SELECT * FROM `orders` WHERE `ID`=LAST_INSERT_ID()")->fetch(PDO::FETCH_ASSOC);

【讨论】:

    【解决方案2】:

    运行您的第一个查询,即插入,然后在该查询成功后获取最后一个 insertid,然后在您的下一个查询中使用该 id.. 例如。

    <?php
    
    
    
    try {
    
            $db = new Database(); //Create a new object of type Database establishing a connection to the MySQL database
    
    
            $query = $db->prepare("INSERT INTO orders (order_type`, `item`, `amount`, `price`, `price_btc`, `status`, `timestamp`, `placed_by`, `secret`, `first_name`, `last_name`, `address_1`, `address_2`, `city`, `zip_code`, `country`, `state`, `phone_number`) VALUES(:order_type, :item, :amount, :price, :price_btc, :status, :timestamp, :placed_by, :secret, :first_name, :last_name, :address_1, :address_2, :city, :zip_code, :country, :state, :phone_number)");
    
            $query->execute(array( /* your values*/ ));
    
    
            $lastId = $db->lastInsertId(); // fetch last insert id, after success.
    
    
            $order = $db->prepare("SELECT * FROM `orders` WHERE `ID`=?");
            $order->bindValue(1, $lastId);
            $order->execute();
            //Fetch your records and display.
    
    
    }
    catch (PDOException $e) {
            echo "Error : " . $e->getMessage();
    
    }
    
    ?>
    

    我像你一样留下了一些代码,但重要的是先运行插入然后收集最后一个

    【讨论】:

    • 谢谢!这正是我所需要的! $db-&gt;lastInsertId(); 函数。
    • 如果有其他语句并行运行,这会导致问题吗?将它放在一个语句中的好处是可以保证执行顺序。
    • @Akumaburn 我不明白你的意思?
    • @MasivuyeCokile 如果您有多个用户同时访问此函数,在 $db 变量是全局变量的情况下。如果在您的 php 工作人员到达 @987654323 之前有另一个 MYSQL 插入会发生什么@ 线?你会得到你的插入,还是其他用户的插入?
    【解决方案3】:

    您认为 PDO 是正确的(我相信任何 PHP 方法?)默认情况下不允许在单个查询中进行多个查询。您可以阅读一些解决方法,了解更多信息,例如:

    PDO support for multiple queries (PDO_MYSQL, PDO_MYSQLND)

    但它们确实增加了 SQL 注入的风险,因此不明智。

    【讨论】:

    • php 中有 mysqli_multi_query 这可以在一次调用中处理多个查询结果,但您需要使用 mysqli_connect 进行连接