php - PDO 的 UPDATE 和 FETCHALL() 规则

标签 php mysql pdo

在我的 SQL 查询中,我有一个 INSERTUPDATE 和一个 SELECT 查询都在一个查询中,如下面的查询

INSERT INTO questions (user_mail, question_id, question, username, created_at) VALUES (:fid, :qid, :com, :pid, :dat);
UPDATE users SET  activity = activity + 1 WHERE face_id = :fid;
SELECT questions.face_id
       FROM  questions
       WHERE questions.question_id = :qid

我在一个 PDO 查询中有所有这三个查询,但是有一个奇怪的规则使用 UPDATE 查询和 $result = $stmt->fetchAll();关于如何解决这个问题的任何想法,因为我的 PDO 不断吐出一个错误,上面写着

SQLSTATE[HY000]: General error

这是组合查询的结果;并且请它强制我结合上面的查询否则我将不得不改变我的整个代码逻辑,其次我已经使用 $result = $stmt->execute ( $params ); 来执行查询,但它从我需要使用 $stmt->fetchAll();SELECT 查询部分返回值。还有别的办法吗?

另一种方式导致另一个问题

cannot execute query while other unbuffered queries are still active

case PUT_COMMENTS :
            $this->querymultiple ['insert'] = "INSERT INTO talks (face_id, comment, phone_id, created_at) VALUES (:fid, :com, :pid, :dat);";

            $this->querymultiple ['update'] = "UPDATE facelog SET  activity = activity + 1 WHERE face_id = :fid;
                                               UPDATE facelog SET  commentCount = commentCount + 1 WHERE face_id = :fid;";

            $this->querymultiple ['select'] = "SELECT
                                                talks.comment,
                                                talks.face_id,
                                                userlog.gcm_id
                                               FROM
                                                    talks,
                                                    tagged,
                                                    userlog
                                               WHERE
                                                   talks.face_id = :fid
                                                   AND talks.comment = :com
                                                   AND tagged.face_id = talks.face_id
                                                   AND userlog.phone_id = tagged.phone_id";

            $this->params ['insert'] = array (
                    ':' . FACE_ID => $value [FACE_ID],
                    ':' . COMMENT => $value [COMMENT],
                    ':' . DATE => $value [DATE],
                    ':' . PHONE_ID => $value [PHONE_ID] 
            );

            $this->params ['update'] = array (
                    ':' . FACE_ID => $value [FACE_ID] 
            );

            $this->params ['select'] = array (
                    ':' . FACE_ID => $value [FACE_ID],
                    ':' . COMMENT => $value [COMMENT] 
            );

            $this->pdo_query->RunMultipleQuery ( $tag, $this->querymultiple, $this->params, SELECT );
            break;

我的RunMultipleQuery()方法如下

/**
 * This method runs multiple the Queries
 *
 * @param unknown $tag          
 * @param unknown $query            
 * @param unknown $params           
 * @param unknown $query_type           
 */
public function RunMultipleQuery($tag, $query, $params, $query_type) {
    try {
        $stmt = array ();
        $result = array ();
        if (! empty ( $query ) || ! empty ( $params )) {
            $this->pdo_db->pdo_db->beginTransaction ();
            $stmt ['insert'] = $this->pdo_db->pdo_db->prepare ( $query ['insert'] );
            $stmt ['update'] = $this->pdo_db->pdo_db->prepare ( $query ['update'] );
            $stmt ['select'] = $this->pdo_db->pdo_db->prepare ( $query ['select'] );

            $result ['insert'] = $stmt ['insert']->execute ( $params ['insert'] );
            $result ['update'] = $stmt ['update']->execute ( $params ['update'] );
            $result ['select'] = $stmt ['select']->execute ( $params ['select'] );

            $stmt ['insert']->closeCursor ();
            $stmt ['update']->closeCursor ();
            $stmt ['select']->closeCursor ();

            $this->pdo_db->pdo_db->commit ();
        } else {
            $result = null;
        }
    } catch ( PDOException $e ) {
        // For testing, you could use a die and message.
        // die("Failed to run query: " . $ex->getMessage());

        // or just use this use this one to product JSON data:
        // $response["message"] = '0:'.$ex->getMessage() ;
        // die(json_encode($response["message"]));
        $error_message = $e->getMessage ();
        $error_code = $e->getCode ();
        $error_trace = $e->getTrace ();
        Log::LogError ( $error_message, $error_code, $error_trace );
        // roll back transaction
        if ($this->pdo_db->pdo_db->inTransaction ()) {
            $this->pdo_db->pdo_db->rollBack ();
        }
        $result = null;
    }

    if ($query_type == SELECT) {
        // echo 'result = '.$result;
        try {
            if (! empty ( $result ['select'] )) {
                // fetching all the rows from the query
                SendtoClient::Toclient ( $tag, $stmt ['select']->fetchAll () );
            } else {
                SendtoClient::Toclient ( $tag, null );
            }
        } catch ( PDOException $e ) {
            $error_message = $e->getMessage ();
            $error_code = $e->getCode ();
            $error_trace = $e->getTrace ();
            Log::LogError ( $error_message, $error_code, $error_trace );
        }
    }
}

最佳答案

应该做的是将您的查询隔离在事务中并逐一发出。我将发布一个示例,说明如何使用准备好的语句执行此操作:

try
{

    $pdo->beginTransaction();

    $stmt['insert'] = $pdo->prepare("INSERT INTO questions (user_mail, question_id, question, username, created_at) VALUES (:fid, :qid, :com, :pid, :dat)");
    $stmt['update'] = $pdo->prepare("UPDATE users SET  activity = activity + 1 WHERE face_id = :fid");
    $stmt['select'] = $pdo->prepare("SELECT questions.face_id FROM  questions WHERE questions.question_id = :qid");

    $stmt['insert']->execute([':fid' => 'your value', ':qid' => 'your value', ':com' => 'your value', ':pid' => 'your value', ':dat' => 'your value']);
    $stmt['update']->execute([':fid' => 'your value']);
    $stmt['select']->execute([':qid' => 'your qid']);

    $rows = $stmt['select']->fetchAll();

    $pdo->commit();
}
catch(\PDOException $e)
{
    echo "Something went terribly wrong: " . $e->getMessage();

    if($pdo->inTransaction())
    {
        $pdo->rollBack();
    }
}

您不应在单个 PDO 函数中发送表示 3 个查询的字符串的原因是:它不起作用。 第二个原因是:很难调试或维护类似的东西。对每种类型的工作进行查询会更清晰。 第三个原因:假设这三个查询可以协同工作,您如何判断哪个查询失败了?

使用准备好的语句可以很好地控制这个流程。使用事务可确保一切按计划进行——如果过程中出现问题,您的数据库将不会被孤立数据破坏。最好的部分 - 您可以捕获异常并检查其错误消息以查看哪个查询出错。

我发布了一个代码示例,您应该使用您计划发送到数据库的值来修改它。从性能 POV 来看,它稍微慢一些(除非您发出大量查询,在这种情况下它会非常快)。

关于php - PDO 的 UPDATE 和 FETCHALL() 规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31519639/

相关文章:

mysql - 带有 PDO 的简单 MySQL SELECT

PHP MYSQL PDO BLOB上传总是空零字节

javascript - Jquery Ajax 向数据库中插入数据

python - 如何将逗号分隔的日期属性列表转换为 MySQL 日期值?

PHP 部署到 windows/unix 服务器

mysql:如果没有找到记录,则避免写入输出文件

mysql - 为 Prestashop 1.6 优化 MySQL

javascript - 连接数据库时最好使用 include 或 include_once

php - 在 php 中使用 javascript 验证复选框

php - 登录页面在 codeigniter 中不起作用