执行数字数组时出现PHP PDO错误

时间:2014-09-06 16:39:03

标签: php mysql sql arrays pdo

我制作了一个向数据库添加订单的脚本。插入时(我可以通过每次用户访问页面时查询数据库50次来完成许多字段,因此必须进入一个查询。

我制作了一个脚本,动态添加链接到数组中给定数据量的选定数量的记录。

但是每当我尝试执行查询时,它都会给我一个错误,即我的语法不正确。

我的代码:

private function addOrderDetails($products, $orderID) {
    # Base of the query (will be the end result)
    $query = 'INSERT INTO `Database`.`orderDetails` (
        `amount`, 
        `price`, 
        `tax`, 
        `product_id`, 
        `order_id`
    ) VALUES (:?, :?, :?, :?, :?)';

    # Added to the query if there are more than 1 products
    $queryExtension = ', (:?, :?, :?, :?, :?)';
    $queryPayload   = array();

    # Loop through all products and add them to the query payload
    foreach ($products as $counter => $productArray) {
        # Add all values individually
        foreach ($productArray as $value) {
            array_push($queryPayload, $value);
        }

        # Add the orderID at the end and extend the query (if the key is more than 0)
        array_push($queryPayload, $orderID);
        if ($counter > 0) $query .= $queryExtension;
    }

    # Execute the array
    $query  = $this->DB->prepare($query);
    $query->execute($queryPayload);        # Error on this exact line, if I put an exit; here it throws no error.
}

包含数据的数组:

array(
    array(
        'amount'    => 50,
        'price'     => 10,
        'tax'       => 2,
        'productID' => 5
    ),
    array(
        'amount'    => 27,
        'price'     => 19,
        'tax'       => 6,
        'productID' => 15
    ),
    array(
        'amount'    => 492,
        'price'     => 2300,
        'tax'       => 4.5,
        'productID' => 50
    )
);

我的错误:

Fatal error:  Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':'50', :'10', :'2', :'5', :'42'), (:'27', :'19', :'6', :'15', :'42'), (:'492', :' at line 7' in (webroot)
Stack trace:
#0 (webroot): PDOStatement->execute(Array)
#1 (webroot): Database->addOrderDetails(Array, '42')
#2 (webroot): Database->addOrder(1, '1', Array)
#3 {main}

1 个答案:

答案 0 :(得分:0)

就像我在评论中所说,命名占位符以冒号开头。您似乎没有使用命名占位符,因此常规问号也可以。 IE用:?替换?

也就是说,您似乎错过了使用预准备语句的最佳部分:您可以使用不同的值重新使用准备好的查询。您正在添加并添加到查询字符串,只需不需要:

$query = 'INSERT INTO `Database`.`orderDetails` (
        `amount`, 
        `price`, 
        `tax`, 
        `product_id`, 
        `order_id`
    ) VALUES (?, ?, ?, ?, ?)';
$stmt = $pdo->prepare($query);
$pdo->beginTransaction();//best use transactions here, though
foreach ($products as $counter => $productArray)
{
    $bind = array_values($productArray);//though strictly speaking, this isn't required
    $stmt->execute($bind);//add this array
    $stmt->closeCursor();
}
$pdo->commit();

预准备语句是预编译的,预优化的查询,只需要输入(即要插入的值)以便执行。如果可以提前编译和优化查询,为什么不能多次使用相同的资源?正如您从上面的代码中看到的那样:可以重新使用该语句,您只需要做它(严格>,但最好是这样做) ,是每次完成语句运行时通知PDO(和DB)。 PDOStatement::closeCursor为您做到这一点。

因为您尝试在一个查询中插入数据,所以我建议使用事务。这样,如果其中一个查询失败,则可以抛出异常,并且您可以撤消您之前运行的所有查询:

try
{
    $pdo->beginTransaction();
    //same code as above
    $pdo->commit();//save changes
}
catch (PDOException $e)
{//something went wrong
    $pdo->rollBack();//undo changes
}