update query over not exist empty collection attribute php symfony doctrine2 doctrine dql

php - query - Combine IS NULL y: valor en Doctrine 2 DQL



mongoose $exists (2)

Como otras (antiguas) preguntas no obtuvieron las respuestas correctas, intentaré de nuevo:

Con frecuencia encuentro un escenario en el que quiero consultar una entidad con un valor específico:

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

A menudo, este valor puede ser NULO, pero WHERE e.parent = NULL no produce resultados, lo que me obliga a hackear de esta manera:

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

Si bien entiendo el razonamiento detrás de NULL! = NULL en SQL / DQL, el hecho es que la consecuencia es realmente molesta en este caso.

Además, un ejemplo dado en una pregunta anterior no funciona en DQL, ¡para NULL! = NULL.

->setParameter(''parent'', (is_null($parent) ? "NULL" : $parent));

También probé de esta manera, lo que alguien amablemente ofreció, pero esto dará una excepción NonUniqueResult, porque cuando parent es 1, por ejemplo, dará un doble resultado.

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

¿Hay una manera más limpia de realizar esta consulta, cuando el parámetro puede ser nulo?


Si no está seguro con respecto a su valor de parámetro, entonces puede volver a escribir su cláusula where

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

Si tiene más filtros para su consulta, asegúrese de usar () alrededor de sus criterios de OR como

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


Si su escenario es así de simple y solo quiere obtener las entidades (y realmente no le importa la consulta), en lugar de DQL puede usar una función de repositorio:

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

lo que automáticamente hará que la condición de SQL sea " parent IS NULL " si $parent es null (sino la condición básica " parent = ? " + parameter).

De lo contrario, agregue una condición en :parent para evitar la excepción NonUniqueResult en su consulta combinada:

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

o incluso (traducción directa de su "hack"):

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

Nota al margen sobre "NULL! = NULL en SQL / DQL":

Estrictamente, tanto "NULL = NULL" como "NULL! = NULL" no son TRUE ni FALSE : ambos devuelven NULL.
Ahora, NULL no es "sincero", por lo que ambas consultas
" SELECT e FROM Entity e WHERE e.parent = NULL " y
" SELECT e FROM Entity e WHERE e.parent != NULL "
nunca devolverá ninguna fila (para cualquier dato),
pero NULL tampoco es "falso" (es un tercer tipo, digamos "indefinido"), y negarlo no cambia eso: "NOT (NULL)" sigue siendo NULL (y no es TRUE), entonces
" SELECT e FROM Entity e WHERE NOT (e.parent = NULL) " y
" SELECT e FROM Entity e WHERE NOT (e.parent != NULL) "
¡nunca regresará ninguna fila tampoco!
De ahí la necesidad de usar los operadores " x IS NULL " y " x IS NOT NULL " (o " NOT (x IS NULL) ") o COALESCE() , o funciones específicas del proveedor como ISNULL() , IFNULL() , NVL() , etc.
(Observación: puede haber casos en los que la "indefinición" se resuelve automáticamente, por ejemplo, en condiciones
" (expresión que produce NULL) O (expresión que se evalúa como TRUE) " o
" (expresión que produce NULL) Y (expresión que se evalúa como FALSE) "
porque " cualquier cosa O VERDADERO" es siempre VERDADERO y " cualquier cosa Y FALSO" es siempre FALSO).