如何使用查询构建器从子查询更新?

How to update from subquery with query builder?

我正在使用 Symfony 5、Doctrine 和 PostgreSQL。

在某些事务存储库中,我正在尝试 运行 下面的代码:

$queryBuilder = $this->em->createQueryBuilder('tr');
$queryBuilder2 = $this->em->createQueryBuilder('t');

$queryBuilder2->select('t.id', 't.status')
    ->where(
        $queryBuilder->expr()->isNotNull('t.timeoutAt'),
        $queryBuilder->expr()->lt('t.timeoutAt', ':timeoutAt'),
        $queryBuilder->expr()->in('t.status', ':status')
    )->setParameters([
        'timeoutAt' => Carbon::now(TimezoneEnum::UTC),
        'status' => ['pending', 'done'],
    ])->getDQL();


$queryBuilder->update()
    ->set(
        't.status',
        'CASE WHEN t.status = :statusPending THEN :statusDone ELSE :statusInProgress END'
    )
    ->set('tr.updatedAt', ':updatedAt')
    ->from($queryBuilder2->getDQL(), 't')
    ->where('t.id = tr.id')
    ->setParameters([
        'updatedAt' => Carbon::now(TimezoneEnum::UTC),
        'statusPending' => 'pending',
        'statusDone' => 'done',
        'statusInProgress' => 'progress',
    ]);



调用 $queryBuilder->getQuery()->getResult(); 后出现错误:

Doctrine\ORM\Query\QueryException : [Syntax Error] line 0, col 37: Error: Expected Doctrine\ORM\Query\Lexer::T_SET, got ','

如果删除 ->from($queryBuilder2->getDQL(), 't') 错误将被修复,但我需要这个 FROM。

$queryBuilder2->getQuery()->getResult()工作完美;

如何正确地将$querybuilder2的sql放到FROM部分?

这应该是你想要的

它将更新状态和 updatedAt,仅用于 'pending' 和 'done' transactions

getSingleScalarResult() 会让您知道更新了多少交易,

根据需要进行更改

return $this->getEntityManager()
            ->createQueryBuilder()
            ->update(Transaction::class, 't')
            ->set('t.status', 'CASE WHEN t.status = :statusPending THEN :statusDone ELSE :statusInProgress END')
            ->set('t.updatedAt', ':updatedAt')
            ->where('t.status IN (:statuses)')
            ->andWhere('t.timeoutAt is NOT NULL')
            ->andWhere('t.timeoutAt < :timeoutAt')
            ->setParameter('statuses', ['pending', 'done'])
            ->setParameter('updatedAt', Carbon::now(TimezoneEnum::UTC))
            ->setParameter('statusPending','pending')
            ->setParameter('statusDone', 'done')
            ->setParameter('statusInProgress', 'progress')
            ->setParameter('timeoutAt', Carbon::now(TimezoneEnum::UTC))
            ->getQuery()
            ->getSingleScalarResult();