PDO:在一次执行SQL INSERT和SELECT多语句之后的FetchAll

时间:2017-03-17 15:49:57

标签: php mysql pdo mariadb

我需要知道如何获取在插入语句之后执行的select语句的结果作为PDO中的一个执行。

我的PDO连接参数如下:

$opt  = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => true];
$conn = new PDO($dsn, $user, $pass, $opt);

我有以下帮助函数,我用于我的PDO语句执行:

function databaseExecute($SQL, $BIND_P, &$BIND_R) {
    global $conn;
    $stmt = $conn->prepare($SQL);

    if ($stmt->execute($BIND_P)) {
        if ($BIND_R !== false) {
            //Type testing is important here
            $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC);
            $stmt->closeCursor();
            if (!$tmp || count($tmp) == 0) {
                return false;
            }

            $BIND_R = $tmp;
        } else {
            $stmt->closeCursor();
        }

        return true;
    }

    $stmt->closeCursor();
    return false;
}

我的功能本身是:

/**
 * Adds the current purchase object to the database table
 * @return true if success
 */
public function pushToDB() {
    global $tbl_purchases;

    //We don't push purchaseID since that field is auto handled by the database

    $sql    = "INSERT INTO " . $tbl_purchases . " (ProductID, UID, TID, GenDate, KeyIDs, Total, Assigned) VALUES (?, ?, ?, ?, ?, ?, ?); SELECT LAST_INSERT_ID();";
    $result = array();
    if (databaseExecute($sql, array(
        $this->getProductID(),
        $this->getUID(),
        $this->getTID(),
        $this->getGenDate(),
        $this->getKeyIDsJSON(),
        $this->getTotal(),
        $this->getAssigned(),
    ), $r)) {
        var_dump($result);
        $this->_setPurchaseID($result[0]);
        return true;
    }
    trigger_error("Purchase::pushToDB - Could not push purchase to database", E_USER_ERROR);
    return false;
}

但这引发了一般错误 致命错误:未捕获PDOException:SQLSTATE [HY000]:当我尝试fetchAll

时出现常规错误

在这种情况下,我如何获得SQL执行的结果?

PS:这里不接受使用两次执行。

2 个答案:

答案 0 :(得分:1)

  

此处不接受使用两次执行。

这只是一种妄想。

使用第二个查询或 - 更好 - 使用专用函数PDO :: LastInsertId()。但是由于你的设计功能设计很差,这可能是一个问题。所以不管是2次查询。

所以将你的功能改为

function databaseExecute($SQL, $BIND_P = array();) {
    global $conn;
    if (!$BIND_P)
    {
        return $conn->query($SQL);
    }
    $stmt = $conn->prepare($SQL);
    $stmt->execute($BIND_P);
    return $stmt;
}

public function pushToDB() {
    global $tbl_purchases;

    //We don't push purchaseID since that field is auto handled by the database

    $sql = "INSERT INTO $tbl_purchases 
            (ProductID, UID, TID, GenDate, KeyIDs, Total, Assigned) 
            VALUES (?, ?, ?, ?, ?, ?, ?)";
    databaseExecute($sql, array(
        $this->getProductID(),
        $this->getUID(),
        $this->getTID(),
        $this->getGenDate(),
        $this->getKeyIDsJSON(),
        $this->getTotal(),
        $this->getAssigned(),
    ));
        $id = databaseExecute("SELECT LAST_INSERT_ID()")->fetchColumn();
        $this->_setPurchaseID($db);
        return true;
    }
}

答案 1 :(得分:0)

您可以更改您的databaseExectute函数,以获取' SecondResult'的额外参数。 (例如),然后将其更改为......

function databaseExecute($SQL, $BIND_P, &$BIND_R,$SecondResult) {
    global $conn;
    $stmt = $conn->prepare($SQL);

    if ($stmt->execute($BIND_P)) {
        if ($BIND_R !== false) {
            //Type testing is important here
            if ($SecondResult) $stmt->nextRowSet(); // this will ensure that the fetchAll will return the data from the 2nd query
            $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC);
            $stmt->closeCursor();
            if (!$tmp || count($tmp) == 0) {
                return false;
            }

            $BIND_R = $tmp;
        } else {
            $stmt->closeCursor();
        }

        return true;
    }

    $stmt->closeCursor();
    return false;
}

我直接在这里输入了这个,我还没有对它进行过测试,但是它应该有效。

另外,我并不是说其他​​评论是错误的,并且可能有更好的方法可以做到这一点,但你可以在同一条语句中运行两个查询'。