【问题标题】:Doctrine Query Builder not working with UPDATE and INNER JOINDoctrine Query Builder 不适用于 UPDATE 和 INNER JOIN
【发布时间】:2013-03-08 11:58:52
【问题描述】:

在我的存储库中,我有这个查询:

$qb = $this->getEntityManager()->createQueryBuilder();
$qb
    ->update('MyBundle:Entity1', 'e1') 
    ->join('e1.Entity2', 'e2')
    ->set('e1.visibile', '1')
    ->andWhere('e2.id = :id')->setParameter("id", 123)
;

抛出这个错误

[Semantical Error] line 0, col 66 near 'e2.id = :id': Error: 'e2' is not defined

我检查了关系,它是正确的。 在查询更新中使用 join 有什么问题吗?

【问题讨论】:

  • e1 是否有 Entity2 成员加入其班级?
  • 尝试打印您的 DQL 以查看可能出现的问题。 ($qb->getQuery()->getDQL())
  • 您的错误与您的代码不匹配 - 错误显示 :use - 您的代码在哪里?
  • 生成的 DQL: UPDATE MyBundle:Entity1 e1 SET e1.visibile = 1 WHERE e2.id = :id
  • @AlessandroPessina 你试试我的答案吗?你有什么错误吗?它应该可以工作,我在我的项目中使用了非常相似的东西

标签: database symfony doctrine-orm dql


【解决方案1】:

您不能对更新和删除查询使用联接。您必须使用子查询。

更新和删除查询不支持联接,因为它不是 支持所有 dbms。它不会在 Doctrine 1 或 原则 2。但是,您可以通过使用子查询获得相同的效果。

http://www.doctrine-project.org/jira/browse/DC-646

如果您使用的是 MySQL,则无法使用子查询。然后您将不得不使用 2 个查询。

在 MySQL 中,您不能修改表并从同一表中选择 子查询

http://dev.mysql.com/doc/refman/5.0/en/subqueries.html

【讨论】:

  • 嗯,通常你加入另一个表,而不是你当前正在更新的表,所以它应该在大多数情况下在 MySQL 中工作。
【解决方案2】:

Doctrine DQL 不支持加入更新。

尝试执行以下操作:

$qb = $this->getEntityManager()->createQueryBuilder();
$qb
    ->update('MyBundle:Entity1', 'e1') 
    ->set('e1.visibile', '1')
    ->where('e1.Entity2 = :id')
    ->setParameter("id", 123)
;

你可以直接设置链接实体的id,只要是主键,就和实体一样,Doctrine会映射它。

我在我的查询中做同样的事情并且它有效。

【讨论】:

【解决方案3】:

尝试使用子查询来代替 Join will not work in DQL while you re doing an update:

LEFT JOIN,或特别是 JOIN 仅在 UPDATE 中受支持 MySQL 的语句。 DQL 抽象了普通 ansi sql 的一个子集,所以 这是不可能的。尝试使用子选择:

$qb = $this->getEntityManager()->createQueryBuilder();
    $qb ->update('MyBundle:Entity1', 'e') 
        ->set('e.visibile', '1')
        ->where('e.id IN (SELECT e1.id FROM Entity1 e1 INNER JOIN e2.Entity2 e2 WHERE e2 = :id')
        ->setParameter("id", 123);

【讨论】:

【解决方案4】:

非常老的问题,但在完整的查询构建器中不包含答案。

所以是的,以下查询无法同步两个表的字段:

$this->createQueryBuilder('v')
    ->update()
    ->join(Pegass::class, 'p', Join::WITH, 'v.identifier = p.identifier')
    ->set('v.enabled', 'p.enabled')
    ->where('p.type = :type')
    ->setParameter('type', Pegass::TYPE_VOLUNTEER)
    ->andWhere('v.enabled <> p.enabled');

如上所述,生成的查询不包含该关系,因为它在所有 dbms 中都缺乏支持。他们还告诉您改用子查询。

所以我就是这样做的(即使使用 2 个查询并且性能较低......):

foreach ([false, true] as $enabled) {
    $qb = $this->createQueryBuilder('v');

    $sub = $this->_em->createQueryBuilder()
        ->select('p.identifier')
        ->from(Pegass::class, 'p')
        ->where('p.type = :type')
        ->andWhere('p.enabled = :enabled');

    $qb
        ->setParameter('type', Pegass::TYPE_VOLUNTEER)
        ->setParameter('enabled', $enabled);

    $qb
        ->update()
        ->set('v.enabled', $enabled)
        ->where($qb->expr()->in('v.identifier', $sub->getDQL()))
        ->getQuery()
        ->execute();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    • 2013-07-04
    • 2017-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多