La cláusula WHERE filtra filas una por una
Un SELECT sin WHERE te devuelve todas las filas de la tabla, y eso casi nunca es lo que buscas. Con WHERE te quedas solo con las filas que cumplen una condición: SQLite recorre la tabla, evalúa la condición fila por fila y conserva aquellas en las que el resultado es verdadero.
Tres filas regresan: Neuromancer, Hyperion y The Martian. La condición year > 1980 se evaluó en cada fila y solo sobrevivieron las que cumplían.
El modelo mental es así: WHERE actúa como un filtro entre FROM y las columnas que seleccionas. Todo lo que dé como resultado verdadero pasa a la salida.
Operadores de comparación
Lo básico funciona como te imaginas:
= para igualdad, != o <> para "distinto de", y <, <=, >, >= para orden. Las comparaciones de cadenas usan los mismos operadores: author = 'Asimov' busca una coincidencia exacta, carácter por carácter.
Un detalle importante: en SQL las comillas simples se usan para literales de cadena. Las comillas dobles son para identificadores (nombres de columnas o tablas). Puede que WHERE author = "Asimov" funcione en SQLite por motivos históricos, pero no es portable y puede fallar de forma silenciosa si la "cadena" coincide con el nombre de alguna columna. Quédate con las comillas simples.
AND, OR y paréntesis: combinar varias condiciones
En la práctica, las consultas suelen combinar varias condiciones. AND exige que ambos lados sean verdaderos; OR se conforma con que al menos uno lo sea:
La primera consulta filtra los libros recientes y cortos. La segunda trae los libros de cualquiera de los dos autores.
Cuando mezclas AND y OR, la precedencia te puede jugar una mala pasada. AND tiene mayor prioridad que OR, así que:
se interpreta como Herbert OR (Gibson AND year > 1980): todos los libros de Herbert sin importar el año, más los de Gibson posteriores a 1980. Seguramente no es lo que querías. Encierra tu intención entre paréntesis:
Ante la duda, mete paréntesis. Al optimizador de consultas le da igual, y la próxima persona que lea el código te lo agradecerá.
NULL no se comporta como un valor cualquiera
Esta es la trampa de la cláusula WHERE en la que todo el mundo cae alguna vez. En SQL, NULL significa "desconocido", y los valores desconocidos no se pueden comparar. column = NULL no devuelve falso: devuelve NULL, y WHERE lo interpreta como "salta esta fila".
IS NULL y IS NOT NULL son los únicos operadores que comprueban NULL directamente. Grábatelo a fuego: cualquier otra comparación contra NULL devuelve NULL y descarta filas sin avisar.
Lo mismo pasa con la negación. WHERE author != 'Asimov' no devuelve las filas donde author IS NULL, porque NULL != 'Asimov' también da NULL. Si quieres incluir los NULLs, tienes que pedirlos de forma explícita: WHERE author != 'Asimov' OR author IS NULL.
IN y BETWEEN: atajos que usarás a diario
IN comprueba si un valor está dentro de una lista. Es una forma mucho más limpia de escribir una cadena de OR:
BETWEEN comprueba si un valor está dentro de un rango, incluyendo ambos extremos:
year BETWEEN 1980 AND 2000 es idéntico a year >= 1980 AND year <= 2000, solo que más corto. Eso sí, ten en cuenta que ambos límites están incluidos. Si los quieres exclusivos, tendrás que escribir las comparaciones a mano.
Un detalle importante sobre IN y NULL: WHERE column NOT IN (1, 2, NULL) no devolverá nunca ninguna fila, porque cualquier comparación con NULL da como resultado NULL. Quita los NULL de la lista o trátalos por separado con IS NULL.
LIKE: búsqueda de patrones en SQL
LIKE permite buscar patrones dentro de cadenas usando dos comodines:
%representa cualquier secuencia de caracteres (incluso ninguno)._representa exactamente un carácter.
Por defecto, el operador LIKE de SQLite no distingue entre mayúsculas y minúsculas para letras ASCII: 'Dune' LIKE 'dune' devuelve verdadero. Esto puede pillarte por sorpresa si vienes de Postgres, donde LIKE sí distingue mayúsculas y ILIKE es la versión que las ignora. (Ojo: SQLite no tiene ILIKE.)
Si necesitas que la comparación distinga entre mayúsculas y minúsculas, tienes dos caminos. El primero es activar el pragma global:
PRAGMA case_sensitive_like = ON;
O usa GLOB, que siempre distingue entre mayúsculas y minúsculas y emplea comodines al estilo Unix (* para cualquier secuencia y ? para un solo carácter):
GLOB 'd*' no devolvería nada aquí: las mayúsculas importan.
Filtrar filas por fecha en SQLite
SQLite guarda las fechas como texto (normalmente YYYY-MM-DD o el formato ISO 8601 completo), así que las comparaciones de cadenas funcionan también como comparaciones de fechas, siempre que respetes el formato ISO:
Como '2024-06-01' < '2024-11-08' se cumple tanto si lo tratas como texto como si lo tratas como fecha, estas consultas funcionan como esperarías. Eso sí, si guardas fechas en cualquier otro formato ('15/01/2024', 'Jan 15 2024'), las comparaciones van a fallar en silencio y darte resultados incorrectos. Usa siempre ISO 8601 — tu yo del futuro te lo agradecerá.
Para cálculos de fechas más complejos (extraer el año, comparar con "hoy"), SQLite incluye las funciones date(), strftime() y julianday(). Las veremos a fondo en el capítulo dedicado a fechas y horas.
Combinando varias condiciones con WHERE
Una consulta que usa varias de estas cláusulas a la vez:
Léelo línea por línea: nos quedamos con las filas que tengan un año conocido, dentro del rango, escritas por uno de dos autores o lo bastante largas, y que no sean borradores. Eso es justo lo que mejor sabe hacer la cláusula WHERE: combinar condiciones pequeñas y legibles para construir filtros precisos.
Dos costumbres que conviene mantener:
- Pon cada condición en su propia línea con sangría. Un
WHERElargo escrito en una sola línea se vuelve ilegible enseguida. - Comenta la intención cuando la condición no sea evidente. Un
-- excluye borradorescuesta poco y ahorra dolores de cabeza.
Siguiente paso: operadores y NULL en detalle
La cláusula WHERE es, en esencia, operadores aplicados a columnas, y NULL cambia silenciosamente el comportamiento de cada operador. La próxima página entra a fondo en el conjunto de operadores de SQLite — aritméticos, concatenación de cadenas con ||, la familia IS, lógica de tres valores — para que las sorpresas dejen de serlo.
Preguntas frecuentes
¿Cómo funciona la cláusula WHERE en SQLite?
WHERE filtra las filas de una consulta evaluando una condición para cada una. Si la condición da verdadero, la fila se conserva; si da falso o NULL, se descarta. Va justo después de FROM: SELECT ... FROM tabla WHERE condicion.
¿Cómo combino varias condiciones en un WHERE de SQLite?
Con AND y OR. AND exige que ambos lados sean verdaderos; OR se conforma con que uno lo sea. Ojo: AND tiene mayor precedencia que OR, así que cuando los mezcles, usa paréntesis para dejarlo claro: WHERE (a OR b) AND c.
¿Por qué WHERE columna = NULL no funciona en SQLite?
NULL significa "desconocido", así que cualquier comparación con = o != devuelve NULL en lugar de verdadero o falso, y las filas solo se conservan cuando la condición es verdadera. Para esto se usan IS NULL e IS NOT NULL, que son los únicos operadores que comprueban directamente si un valor es NULL.
¿La cláusula WHERE de SQLite distingue mayúsculas con LIKE?
Por defecto, LIKE no distingue mayúsculas y minúsculas en caracteres ASCII: 'Hello' LIKE 'hello' es verdadero. Si necesitas que distinga, activa PRAGMA case_sensitive_like = ON; o usa GLOB, que siempre distingue mayúsculas y emplea comodines al estilo Unix (* y ?).