Объедините IS NULL и: значение в DQL Doctrine 2

Поскольку другие (старые) вопросы не получили правильных ответов, я попробую еще раз:

Я регулярно сталкиваюсь со сценарием, где я хочу запросить объект с определенным значением:

$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);
}

Хотя я понимаю обоснование NULL! = NULL в SQL / DQL, на самом деле последствия действительно раздражают в этом случае.

Кроме того, пример, приведенный в предыдущем вопросе, не работает в 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)

Есть ли более чистый способ выполнить этот запрос, когда параметр может быть нулевым?

6

Решение

Если вы не уверены в значении параметра, вы можете переписать предложение 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...
5

Другие решения

Если ваш сценарий действительно такой простой и вы просто хотите получить сущности (и на самом деле не заботитесь о запросе), то вместо DQL вы можете использовать функцию репозитория:

$entities = $em->getRepository('Entity')->findBy(array('parent' => $parent));

который автоматически устанавливает особый случай условия SQL какparent IS NULL» если $parent является null (иначе основное условие «parent = ?«+ параметр).

В противном случае добавьте условие на :parent чтобы избежать исключения NonUniqueResult в комбинированном запросе:

SELECT e
FROM Entity e
WHERE (e.parent = :parent OR (e.parent IS NULL AND :parent IS NULL))

или даже (в прямом переводе с вашего «хака»):

WHERE ((:parent IS NULL AND e.parent IS NULL) OR (:parent IS NOT NULL AND e.parent = :parent))

Примечание о «NULL! = NULL в SQL / DQL»:

Строго говоря, «NULL = NULL» и «NULL! = NULL» не являются ни ИСТИННЫМИ, ни ЛОЖНЫМИ: оба возвращают NULL.
Теперь NULL не является «правдивым», поэтому оба запроса
«SELECT e FROM Entity e WHERE e.parent = NULL» а также
«SELECT e FROM Entity e WHERE e.parent != NULL«
никогда не вернет ни одной строки (для любых данных),
но NULL также не является «ложным» (это третий тип, скажем, «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)«
никогда не вернет ни одной строки!
Отсюда необходимость использования операторов »x IS NULL» а также «x IS NOT NULL» (или же «NOT (x IS NULL)«) или же COALESCE()или специфичные для поставщика функции, такие как ISNULL(), IFNULL(), NVL(), так далее.
(Примечание: могут быть случаи, когда «неопределенность» решается автоматически, например, в условиях
«(выражение, которое дает NULL) ИЛИ ЖЕ (выражение, которое оценивается как ИСТИНА)» или же
«(выражение, которое дает NULL) А ТАКЖЕ (выражение, которое оценивается как ЛОЖЬ)«
так как «что-нибудь ИЛИ ИСТИНА «всегда ИСТИНА и»что-нибудь И ЛОЖЬ «всегда ЛОЖЬ.)

2

По вопросам рекламы [email protected]