在Doctrine 2 DQL中组合IS NULL和:value

Mat*_*eno 6 php doctrine dql symfony doctrine-orm

由于其他(旧)问题没有得到正确答案,我会再试一次:

我经常遇到一个场景,我想查询具有特定值的实体:

$query = $em->createQuery('SELECT e FROM Entity e WHERE e.parent = :parent');
$query->setParameter('parent', $parent);
Run Code Online (Sandbox Code Playgroud)

通常,此值可以为NULL,但WHERE e.parent = NULL不会产生任何结果,从而迫使我像这样破解:

if ($parent === null) {
    $query = $em->createQuery('SELECT e FROM Entity e WHERE e.parent IS NULL');
}
else {
    $query = $em->createQuery('SELECT e FROM Entity e WHERE e.parent = :parent');
    $query->setParameter('parent', $parent);      
}
Run Code Online (Sandbox Code Playgroud)

虽然我理解SQL/DQL中NULL!= NULL背后的基本原理,但事实是,在这种情况下结果真的很烦人.

此外,旧问题中给出的示例在DQL中不起作用,因为NULL!= NULL.

->setParameter('parent', (is_null($parent) ? "NULL" : $parent));
Run Code Online (Sandbox Code Playgroud)

我也试过这种方式,有人提供了什么,但这会给出一个NonUniqueResult异常,因为例如当parent为1时,它会给出一个双重结果.

SELECT e 
FROM Entity e 
WHERE (e.parent = :parent OR e.parent IS NULL)
Run Code Online (Sandbox Code Playgroud)

当参数可以为null时,是否有更简洁的方法来执行此查询?

M K*_*aid 5

如果您不确定您的参数值,那么您可以将where子句重写为

SELECT e 
FROM Entity e 
WHERE (e.parent = :parent OR e.parent IS NULL)
Run Code Online (Sandbox Code Playgroud)

如果您的查询还有其他过滤器,请务必使用()您的OR标准

SELECT e 
FROM Entity e 
WHERE (e.parent = :parent OR e.parent IS NULL)
AND e.some = :some...
Run Code Online (Sandbox Code Playgroud)


use*_*410 5

如果您的场景真的那么简单并且您只想获取实体(并且并不真正关心查询),那么您可以使用存储库功能代替 DQL:

$entities = $em->getRepository('Entity')->findBy(array('parent' => $parent));
Run Code Online (Sandbox Code Playgroud)

这将自动将 SQL 条件特例为“ parent IS NULL” if $parentis null(否则为基本条件“ parent = ?” + 参数)。

否则,添加条件 on:parent以避免在组合查询中出现 NonUniqueResult 异常:

SELECT e 
FROM Entity e 
WHERE (e.parent = :parent OR (e.parent IS NULL AND :parent IS NULL))
Run Code Online (Sandbox Code Playgroud)

甚至(直接从你的“hack”翻译过来):

WHERE ((:parent IS NULL AND e.parent IS NULL) OR (:parent IS NOT NULL AND e.parent = :parent))
Run Code Online (Sandbox Code Playgroud)

关于“NULL != NULL in SQL / DQL”的旁注

严格来说,"NULL = NULL" 和 "NULL != NULL"既不是 TRUE 也不是 FALSE:两者都返回 NULL。
现在,NULL 不是“真实”,所以查询
SELECT e FROM Entity e WHERE e.parent = NULL”和
SELECT e FROM Entity e WHERE e.parent != NULL
都不会返回任何行(对于任何数据),
但 NULL 也不是“假的”(它是第三种,比如“未定义” "),并否定它不会改变这一点:"NOT (NULL)" 仍然是 NULL(而不是 TRUE),所以
" SELECT e FROM Entity e WHERE NOT (e.parent = NULL)" 和
" SELECT e FROM Entity e WHERE NOT (e.parent != NULL)"
也永远不会返回任何行!
因此需要使用运算符“ x IS NULL”和“ x IS NOT NULL”(或“ NOT (x IS NULL)”)或COALESCE()ISNULL()IFNULL()NVL()
(备注:在某些情况下,“未定义”会自动解决,例如在条件
(产生 NULL 的表达式 OR (计算结果为 TRUE 的表达式) ”或
(产生 NULL 的表达式 AND (计算结果为 FALSE 的表达式)
因为“任何事或真”始终为真,而“任何事与假”始终为假。)