How to fix "Error: Expected Literal, got 'SELECT'" with queryBuilder?
How to fix "Error: Expected Literal, got 'SELECT'" with queryBuilder?
我的查询有问题,当我尝试进行子查询时出现此错误消息
"hydra:description": "[Syntax Error] line 0, col 85: Error: Expected Literal, got 'SELECT'",
对于我的 EventRepositoty 中的这个查询 CLass:
public function updateMoveAtField(string $eventLabel, $cameraId)
{
$queryBuilder = $this->createQueryBuilder('e');
$subQueryBuilder = $this->createQueryBuilder('ev');
$subQuery = $subQueryBuilder
->select('MAX(ev.arrivedAt) as arrived')
->andWhere('ev.camera = ?1')
->setParameter(1, $cameraId)
->getQuery()->getDQL()
;
$event = $queryBuilder
->update()
->set('e.moveAt', '?1')
->where('e.label = ?2')
->andWhere('e.camera = ?3')
->andWhere($queryBuilder->expr()->andX($subQuery))
->setParameter(1, new \DateTime())
->setParameter(2, $eventLabel)
->setParameter(3, $cameraId);
return $event->getQuery()->execute();
}
我该如何解决?
我不知道你是否能理解我的要求所以让我解释一下:我想更新一个字段 "moveAt" 当标签和相机与查询中发送的相同时。所以我做了一个子查询,因为我想要和其他条件(总是更新最后一个)。我做了一个子查询,因为我不能在更新查询中添加 select。
编辑:
来自@Preciel 帮助的 DQL 转储结果
"SELECT MAX(e.arrivedAt) FROM App\Entity\Event e WHERE e.label=:var2
AND e.camera=:var3 AND e.camera=:var3 AND (e.arrivedAt <= SELECT
MAX(e.arrivedAt) FROM App\Entity\Event e WHERE e.label=:var2 AND
e.camera=:var3 AND e.camera=:var3)"
新=
"UPDATE App\Entity\Event e SET event.moveAt = :var1 WHERE
e.label=:var2 AND e.camera=:var3 AND e.arrivedAt <= SELECT
MAX(ev.arrivedAt) FROM App\Entity\Event ev WHERE ev.camera=:var3"
子查询
"SELECT MAX(ev.arrivedAt) FROM App\Entity\Event ev WHERE
ev.camera=:var3"
我会尝试做这样的事情:
public function updateMoveAtField($eventLabel, $cameraId) {
$qb=$this->createQueryBuilder("event");
$sqb=$this->createQueryBuilder("eventBis");
$qb->update()
->set("event.moveAt", ":var1")
->andWhere("event.lavel=:var2")
->andWhere("event.camera=:var3")
->andWhere(
$qb->expr()->lte("event.arrivedAt",
"(".$sqb->select($qb->expr()->max("eventBis.arrivedAt")) //Your sub query start here
->andWhere("eventBis.camera=:var3")->getDQL().")")) //and end here
->setParameters(array(
'var1'=>new \DateTime(),
'var2'=>$eventLabel,
'var3'=>$cameraId,
));
// dump($qb->getDQL());
// dump($qb->getQuery()->getSQL());
// exit();
return $qb->getQuery()->execute();
}
我添加了 2 行转储。如果不行,请先转储DQL,然后SQL(SQL可能会失败),请在评论中添加。
在第一次使用expr()
时,我使用了lte()
(小于等于)。
根据您的需要更改它(gt()、gte()、eq()、lte()、lt())。
提示:
- 始终在查询中使用双引号。 Doctrine 将只接受字符串值的单引号(单引号可以用于参数)。
- 从不使用
where()
,始终以 andWhere()
或 orWhere()
开头
- 避免同时使用
andWhere()
和 orWhere()
。更喜欢 expr()
(read more here)
- 避免将 DQL 与伪原生(
LIKE
、IN
等)混合使用 SQL。如果 Doctrine 阅读一些它不能使用的本地 SQL ,它会咀嚼你。请改用 expr()
。如果您在 expr()
中找不到您需要的内容,则意味着您应该创建一个本机查询。
- 完整命名您的别名,以便以后阅读。
[编辑]
这是我的回答中给出的转储查询的屏幕截图。
我认为您试图使我的查询适应您的代码,而不仅仅是 copy/paste 它。别名与我在查询中写的不匹配。
除了别名,我们还可以看到子查询周围少了一对括号。刚刚在我的回答中添加了它们。如果您 copy/paste 我的代码,它应该可以解决您的问题。
我的查询有问题,当我尝试进行子查询时出现此错误消息
"hydra:description": "[Syntax Error] line 0, col 85: Error: Expected Literal, got 'SELECT'",
对于我的 EventRepositoty 中的这个查询 CLass:
public function updateMoveAtField(string $eventLabel, $cameraId)
{
$queryBuilder = $this->createQueryBuilder('e');
$subQueryBuilder = $this->createQueryBuilder('ev');
$subQuery = $subQueryBuilder
->select('MAX(ev.arrivedAt) as arrived')
->andWhere('ev.camera = ?1')
->setParameter(1, $cameraId)
->getQuery()->getDQL()
;
$event = $queryBuilder
->update()
->set('e.moveAt', '?1')
->where('e.label = ?2')
->andWhere('e.camera = ?3')
->andWhere($queryBuilder->expr()->andX($subQuery))
->setParameter(1, new \DateTime())
->setParameter(2, $eventLabel)
->setParameter(3, $cameraId);
return $event->getQuery()->execute();
}
我该如何解决?
我不知道你是否能理解我的要求所以让我解释一下:我想更新一个字段 "moveAt" 当标签和相机与查询中发送的相同时。所以我做了一个子查询,因为我想要和其他条件(总是更新最后一个)。我做了一个子查询,因为我不能在更新查询中添加 select。
编辑: 来自@Preciel 帮助的 DQL 转储结果
"SELECT MAX(e.arrivedAt) FROM App\Entity\Event e WHERE e.label=:var2 AND e.camera=:var3 AND e.camera=:var3 AND (e.arrivedAt <= SELECT MAX(e.arrivedAt) FROM App\Entity\Event e WHERE e.label=:var2 AND e.camera=:var3 AND e.camera=:var3)"
新=
"UPDATE App\Entity\Event e SET event.moveAt = :var1 WHERE e.label=:var2 AND e.camera=:var3 AND e.arrivedAt <= SELECT MAX(ev.arrivedAt) FROM App\Entity\Event ev WHERE ev.camera=:var3"
子查询
"SELECT MAX(ev.arrivedAt) FROM App\Entity\Event ev WHERE ev.camera=:var3"
我会尝试做这样的事情:
public function updateMoveAtField($eventLabel, $cameraId) {
$qb=$this->createQueryBuilder("event");
$sqb=$this->createQueryBuilder("eventBis");
$qb->update()
->set("event.moveAt", ":var1")
->andWhere("event.lavel=:var2")
->andWhere("event.camera=:var3")
->andWhere(
$qb->expr()->lte("event.arrivedAt",
"(".$sqb->select($qb->expr()->max("eventBis.arrivedAt")) //Your sub query start here
->andWhere("eventBis.camera=:var3")->getDQL().")")) //and end here
->setParameters(array(
'var1'=>new \DateTime(),
'var2'=>$eventLabel,
'var3'=>$cameraId,
));
// dump($qb->getDQL());
// dump($qb->getQuery()->getSQL());
// exit();
return $qb->getQuery()->execute();
}
我添加了 2 行转储。如果不行,请先转储DQL,然后SQL(SQL可能会失败),请在评论中添加。
在第一次使用expr()
时,我使用了lte()
(小于等于)。
根据您的需要更改它(gt()、gte()、eq()、lte()、lt())。
提示:
- 始终在查询中使用双引号。 Doctrine 将只接受字符串值的单引号(单引号可以用于参数)。
- 从不使用
where()
,始终以andWhere()
或orWhere()
开头
- 避免同时使用
andWhere()
和orWhere()
。更喜欢expr()
(read more here) - 避免将 DQL 与伪原生(
LIKE
、IN
等)混合使用 SQL。如果 Doctrine 阅读一些它不能使用的本地 SQL ,它会咀嚼你。请改用expr()
。如果您在expr()
中找不到您需要的内容,则意味着您应该创建一个本机查询。 - 完整命名您的别名,以便以后阅读。
[编辑]
这是我的回答中给出的转储查询的屏幕截图。 我认为您试图使我的查询适应您的代码,而不仅仅是 copy/paste 它。别名与我在查询中写的不匹配。
除了别名,我们还可以看到子查询周围少了一对括号。刚刚在我的回答中添加了它们。如果您 copy/paste 我的代码,它应该可以解决您的问题。