19

我正在尝试使用 Doctrine QueryBuilder 来执行以下 SQL 查询:

DELETE php FROM product_hole_pattern php
INNER JOIN hole_pattern hp ON php.hole_pattern_id = hp.id
INNER JOIN hole_pattern_type hpt ON hp.hole_pattern_type_id = hpt.id
WHERE php.product_id = 4 AND hpt.slug='universal';

我有这个

$qb = $this->entityManager->createQueryBuilder();
$query = $qb->delete('\SANUS\Entity\ProductHolePattern', 'php')
  ->innerJoin('php.holePattern', 'hp')
  ->innerJoin('hp.holePatternType', 'hpt')
  ->where('hpt.slug = :slug AND php.product=:product')
  ->setParameter('slug','universal')
  ->setParameter('product',$this->id)
  ->getQuery();

但我得到:

[Semantical Error] line 0, col 50 near 'hpt.slug = :slug': Error: 'hpt' is not defined.

错误消息附带的 DQL 是:

DELETE \SANUS\Entity\ProductHolePattern php 
WHERE hpt.slug = :slug AND php.product=:product

所以连接似乎完全被省略了。

4

4 回答 4

16

使用 IN 条件运行查询可能比迭代更好。

$ids = $this->createQueryBuilder('product')
->join('..your joins..')
->where('..your wheres..')
->select('product.id')
->getQuery()->getResult();

$this->createQueryBuilder('product')
    ->where('product.id in (:ids)')
    ->setParameter('ids', $ids)
    ->delete()
    ->getQuery()
    ->execute();
  • 好处:运行速度更快,无需迭代
  • 缺点:你不能挂钩 preRemove

至于“放哪里”的激烈争论,如果你愿意,敢把它放在控制器中。这完全取决于你。但是,如果您将代码放在专用的学说存储库类中,将来它可能对您更有用。它应该很容易做到,并且易于更改/维护。

于 2018-09-24T21:39:09.457 回答
13

看起来 DQL 不支持这种删除语句。Doctrine 文档中的BNF表明 adelete_statement必须采用以下形式

delete_clause [where_clause]

其中delete_clause定义为:

"DELETE" "FROM" abstract_schema_name [["AS"] identification_variable]

所以我可以提供一个模式和一个 where 子句,但没有连接。

于 2013-06-25T15:57:14.653 回答
4

实现此目的的一种方法可能是首先使用连接查询要删除的实体:

$qb = $this->entityManager->createQueryBuilder();
$query = $qb->select('\SANUS\Entity\ProductHolePattern', 'php')
  ->innerJoin('php.holePattern', 'hp')
  ->innerJoin('hp.holePatternType', 'hpt')
  ->where('hpt.slug = :slug AND php.product=:product')
  ->setParameter('slug','universal')
  ->setParameter('product',$this->id)
  ->getQuery();
$results = $query->execute();

然后删除您在结果中找到的实体:

foreach ($results as $result) {
  $this->entityManager->remove($result);
}

一定要打电话

$this->entityManager->flush();

在应用程序的适当位置(通常是控制器)。

于 2013-07-25T15:41:20.680 回答
-6

在 Symfony2 上,请尝试:

foreach ($results as $result) {
  $em->remove($result);
}

$em->flush();

就这样。

于 2014-11-10T21:55:15.290 回答