簡體   English   中英

Doctrine 使用子查詢更新查詢

[英]Doctrine Update query with a sub-query

我正在嘗試使用 doctrine dql 執行類似於以下查詢的查詢:

Doctrine_Query::create()
              ->update('Table a')
              ->set('a.amount',
                    '(SELECT sum(b.amount) FROM Table b WHERE b.client_id = a.id AND b.regular = ? AND b.finished = ?)',
                    array(false, false))
              ->execute();

但它會引發一個 Doctrine_Query_Exception 消息:“未知組件別名 b”

在'set'子句中使用子查詢是否有限制,你能給我一些幫助嗎?

提前致謝。

多年后,但可能會有所幫助。

是的 ]

如果您需要/想要/必須這樣做,您可以使用Querybuilder執行具有子 select 語句的更新查詢,而不是直接使用底層連接層。
這里的想法是使用 QueryBuilder 兩次。

  • 構建 select 語句來計算新值。
  • 構建實際的更新查詢以提交到數據庫,您將在其中注入以前的 select DQL,如您所料,以便發出單個數據庫請求。

例子 ]

給定一個用戶可以出售對象的應用程序。 每筆交易都涉及買方和賣方。 交易結束后,賣家和買家可以對交易如何與對方進行評論。
您可能需要一個User表、一個Review表和一個Transaction表。
User 表包含一個名為rating的字段,它將保存用戶的平均評分。 Review 表存儲一個事務 id、作者 id(提交評論的人)、一個值(從 0 到 5)。 最后,交易包含買賣雙方的參考。

現在假設您想在對方提交評論后更新用戶的平均評分。 更新查詢將計算用戶的平均評分並將結果作為User.rating屬性的值。
我將以下代碼段與Doctrine 2.5Symfony3 一起使用 由於這項工作是關於用戶的,因此我在AppBundle\Entity\UserRepository.php存儲庫中創建一個名為updateRating( User $user)的新公共 function 是有意義的。

/**
 * Update the average rating for a user
 * @param User $user The user entity object target
 */
public function updateRating( User $user )
{
    // Compute Subrequest. The reference table being Transaction, we get its repository first.
    $transactionRepo = $this->_em->getRepository('AppBundle:Transaction');
    $tqb = $postRepo->createQueryBuilder('t');
    #1 Computing select
    $select = $tqb->select('SUM(r.value)/count(r.value)')
        // My Review table as no association declared inside annotation (because I do not need it elsewhere)
        // So I need to specify the glue part in order join the two tables
        ->leftJoin('AppBundle:Review','r', Expr\Join::WITH, 'r.post = p.id AND r.author <> :author')
        // In case you have an association declared inside the Transaction entity schema, simply replace the above leftJoin with something like
        // ->leftJoin(t.reviews, 'r')
        // Specify index first (Transaction has been declared as terminated)
        ->where( $tqb->expr()->eq('t.ended', ':ended') )
        // The user can be seller or buyer
        ->andWhere( $tqb->expr()->orX(
            $tqb->expr()->eq('t.seller', ':author'),
            $tqb->expr()->eq('t.buyer', ':author')
        ));
    #2 The actual update query, containing the above sub-request
    $update = $this->createQueryBuilder('u')
        // We want to update a row
        ->update()
        // Setting the new value using the above sub-request
        ->set('u.rating', '('. $select->getQuery()->getDQL() .')')
        // should apply to the user we want
        ->where('u.id = :author')
        // Set parameters for both the main & sub queries
        ->setParameters([ 'ended' => 1, 'author' => $user->getId() ]);
    // Get the update success status
    return $update->getQuery()->getSingleScalarResult();
}

現在從 controller

            // … Update User's rating
            $em->getRepository('AppBundle:User')->updateRating($member);
            // …

我不確定這是否有限制,但我記得前一段時間曾與此作斗爭。 我最終得到了它的工作:

$q = Doctrine_Manager::getInstance()->getCurrentConnection();
$q->execute("UPDATE table a SET a.amount = (SELECT SUM(b.amount) FROM table b WHERE b.client_id = a.id AND b.regular = 0 AND b.finished = 0)");

看看這是否能解決問題。 請注意,自動變量 escaping 不會通過此查詢執行,因為它不是 DQL。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM