在 Doctrine 2 DQL 中结合 IS NULL 和 :value
Combine IS NULL and :value in Doctrine 2 DQL
由于其他(旧)问题没有得到正确的答案,我会再试一次:
我经常遇到这样一种情况,我想查询具有特定值的实体:
$query = $em->createQuery('SELECT e FROM Entity e WHERE e.parent = :parent');
$query->setParameter('parent', $parent);
通常,这个值可以为 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);
}
虽然我理解 SQL / DQL 中 NULL != NULL 背后的基本原理,但事实是,在这种情况下,后果真的很烦人。
此外,较旧问题中给出的示例在 DQL 中不起作用,因为 NULL != NULL。
->setParameter('parent', (is_null($parent) ? "NULL" : $parent));
我也试过这种方法,有人好心提供的,但这会给出一个 NonUniqueResult 异常,因为例如当 parent 为 1 时,它会给出一个双精度结果。
SELECT e
FROM Entity e
WHERE (e.parent = :parent OR e.parent IS NULL)
当参数可以为 null 时,是否有更简洁的方法来执行此查询?
如果您不确定参数值,则可以将 where 子句重写为
SELECT e
FROM Entity e
WHERE (e.parent = :parent OR e.parent IS NULL)
如果您的查询有更多过滤器,请确保在您的 OR
条件周围使用 ()
,例如
SELECT e
FROM Entity e
WHERE (e.parent = :parent OR e.parent IS NULL)
AND e.some = :some...
如果您的场景真的那么简单,您只想获取实体(并不真正关心查询),那么您可以使用存储库函数代替 DQL:
$entities = $em->getRepository('Entity')->findBy(array('parent' => $parent));
如果 $parent
是 null
,它将自动 special-case SQL 条件为“parent IS NULL
”(否则基本条件“parent = ?
" + 参数).
否则,在 :parent
上添加条件以避免在组合查询中出现 NonUniqueResult 异常:
SELECT e
FROM Entity e
WHERE (e.parent = :parent OR (e.parent IS NULL AND :parent IS NULL))
甚至(直接从您的 "hack" 翻译):
WHERE ((:parent IS NULL AND e.parent IS NULL) OR (:parent IS NOT NULL AND e.parent = :parent))
旁注 关于 "NULL != NULL in SQL / DQL":
严格来说,"NULL = NULL" 和 "NULL != NULL" 既不是 TRUE 也不是 FALSE:两者都是 return NULL。
现在,NULL 不是 "truthy",所以两个查询
“SELECT e FROM Entity e WHERE e.parent = NULL
”和
“SELECT e FROM Entity e WHERE e.parent != NULL
”
永远不会 return 任何行(对于任何数据),
但是 NULL 也不是 "falsy"(它是第三种,比如说 "undefined"),并且否定它不会改变:"NOT (NULL)" 仍然是 NULL(而不是 TRUE),所以
“SELECT e FROM Entity e WHERE NOT (e.parent = NULL)
”和
“SELECT e FROM Entity e WHERE NOT (e.parent != NULL)
”
也不会 return 任何行!
因此需要使用运算符“x IS NULL
”和“x IS NOT NULL
”(或“NOT (x IS NULL)
”)或COALESCE()
,或vendor-specific函数,如[=26] =]、IFNULL()
、NVL()
等
(备注:在某些情况下 "undefinedness" 会自动解决,例如在条件
“(产生 NULL 的表达式) OR (计算结果为 TRUE 的表达式)”或
“(产生 NULL 的表达式) AND (计算结果为 FALSE 的表达式)”
因为“anything OR TRUE”始终为 TRUE,而“anything AND FALSE”始终为 FALSE。)
由于其他(旧)问题没有得到正确的答案,我会再试一次:
我经常遇到这样一种情况,我想查询具有特定值的实体:
$query = $em->createQuery('SELECT e FROM Entity e WHERE e.parent = :parent');
$query->setParameter('parent', $parent);
通常,这个值可以为 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);
}
虽然我理解 SQL / DQL 中 NULL != NULL 背后的基本原理,但事实是,在这种情况下,后果真的很烦人。
此外,较旧问题中给出的示例在 DQL 中不起作用,因为 NULL != NULL。
->setParameter('parent', (is_null($parent) ? "NULL" : $parent));
我也试过这种方法,有人好心提供的,但这会给出一个 NonUniqueResult 异常,因为例如当 parent 为 1 时,它会给出一个双精度结果。
SELECT e
FROM Entity e
WHERE (e.parent = :parent OR e.parent IS NULL)
当参数可以为 null 时,是否有更简洁的方法来执行此查询?
如果您不确定参数值,则可以将 where 子句重写为
SELECT e
FROM Entity e
WHERE (e.parent = :parent OR e.parent IS NULL)
如果您的查询有更多过滤器,请确保在您的 OR
条件周围使用 ()
,例如
SELECT e
FROM Entity e
WHERE (e.parent = :parent OR e.parent IS NULL)
AND e.some = :some...
如果您的场景真的那么简单,您只想获取实体(并不真正关心查询),那么您可以使用存储库函数代替 DQL:
$entities = $em->getRepository('Entity')->findBy(array('parent' => $parent));
如果 $parent
是 null
,它将自动 special-case SQL 条件为“parent IS NULL
”(否则基本条件“parent = ?
" + 参数).
否则,在 :parent
上添加条件以避免在组合查询中出现 NonUniqueResult 异常:
SELECT e
FROM Entity e
WHERE (e.parent = :parent OR (e.parent IS NULL AND :parent IS NULL))
甚至(直接从您的 "hack" 翻译):
WHERE ((:parent IS NULL AND e.parent IS NULL) OR (:parent IS NOT NULL AND e.parent = :parent))
旁注 关于 "NULL != NULL in SQL / DQL":
严格来说,"NULL = NULL" 和 "NULL != NULL" 既不是 TRUE 也不是 FALSE:两者都是 return NULL。
现在,NULL 不是 "truthy",所以两个查询
“SELECT e FROM Entity e WHERE e.parent = NULL
”和
“SELECT e FROM Entity e WHERE e.parent != NULL
”
永远不会 return 任何行(对于任何数据),
但是 NULL 也不是 "falsy"(它是第三种,比如说 "undefined"),并且否定它不会改变:"NOT (NULL)" 仍然是 NULL(而不是 TRUE),所以
“SELECT e FROM Entity e WHERE NOT (e.parent = NULL)
”和
“SELECT e FROM Entity e WHERE NOT (e.parent != NULL)
”
也不会 return 任何行!
因此需要使用运算符“x IS NULL
”和“x IS NOT NULL
”(或“NOT (x IS NULL)
”)或COALESCE()
,或vendor-specific函数,如[=26] =]、IFNULL()
、NVL()
等
(备注:在某些情况下 "undefinedness" 会自动解决,例如在条件
“(产生 NULL 的表达式) OR (计算结果为 TRUE 的表达式)”或
“(产生 NULL 的表达式) AND (计算结果为 FALSE 的表达式)”
因为“anything OR TRUE”始终为 TRUE,而“anything AND FALSE”始终为 FALSE。)