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).