Null (SQL)
# Null (SQL)

Null (nulo) es un marcador especial usado en el lenguaje de consulta estructurado (SQL) para indicar que no existe un valor dentro de una base de datos. Introducido por el creador del modelo relacional de bases de datos E. F. Codd, su función es la de solventar el requisito de que los sistemas de gestión relacionales de base de datos (en inglés: Database management system, abreviado DBMS) verdaderos puedan representar información “desconocida” o “no aplicable”. Asimismo, Codd también introdujo el uso de la letra griega omega (ω) en minúscula para representar el Null en la teoría de la teoría de las bases de datos. NULL es también una palabra reservada en el lenguaje SQL para identificar el marcador especial Null.

Null ha sido un foco de controversia y una fuente de debate debido a su asociación a la lógica ternaria (en inglés: Three-Valued Logic, abreviado 3VL), a sus restricciones de uso en SQL y a la dificultad de su manejo en SQL. Aunque las funciones especiales y predicados sirven para manejar eficazmente el Nulls, la competencia opina que resolver este tipo de cuestiones añade complejidades y contradicciones innecesarias dentro del modelo relacional de bases de datos.

## Historia

Null fue introducido por E. F. Codd como un método de representación de datos que faltan en el modelo relacional. Codd más tarde reforzó su llamamiento para que todos los RDBMS’ incluyeran la función null para indicar los datos que faltan en un doble artículo publicado en la revista ComputerWorld. Codd también introdujo la lógica ternaria, consistente en la veracidad de los valores True (verdadero), False (falso), y Desconocido (Unknown), los cuales están estrechamente relacionados con el concepto de Null. El valor Desconocido verdadero es generado cuando Null es comparado con cualquier dato, o con otro Null.

Codd indicó en su libro “The Relational Model for Database Management publicado en 1990, Version 2” que un solo mandato Null a través del estándar SQL era inadecuado, y debería ser reemplazado por dos marcadores Null separados para indicar la razón de por qué los datos faltan. Estos dos tipos de marcadores Null son llamados comúnmente “Valores A” y “Valores I”, representando “datos que faltan pero aplicables” y “datos que faltan pero no aplicables”, respectivamente. La recomendación de Codd debería haber requerido una expansión del sistema lógico del SQL para acomodar el sistema lógico cuaternario. Debido a su adicional complejidad, la idea de los múltiples valores Null no ha logrado un reconocimiento general.

## Lógica ternaria (Three-valued logic -3VL-)

Debido a que no pertenece a ningún dominio de datos, Null no está considerado propiamente un “valor”, pero realmente sí que es un marcador que indica la ausencia de un valor. Debido a esto, las comparaciones con Null nunca resultan ciertas o falsas, pero si como un resultado lógico ternario, desconocidas (unknown). El resultado lógico de la siguiente expresión, la cual compara el valor 10 con Null, es Desconocido:

De todas formas, ciertas operaciones con Null pueden devolver valores si el valor Null no es relevante ante el resultado de la operación. Es el caso del siguiente ejemplo, considerando que la declaración OR es evaluada en forma de giro corto:

En este caso, el hecho de que el valor a la derecha de OR es desconocido es irrelevante, porque el resultado de la operación debería ser Verdadera a pesar del valor de la derecha. SQL aplica resultados lógicos ternarios, luego las aplicaciones de SQL deben proporcionar unos valores lógicos ternarios especializados. Las reglas que gobiernan los valores lógicos ternarios en SQL se muestran en las siguientes tablas (p y q representan estados lógicos):

| p AND q | p AND q | p | p | p |
| - | - | - | - | - |
| p AND q | p AND q | Verdadero | Falso | Desconocido |
| q | Verdadero | Verdadero | Falso | Desconocido |
| q | Falso | Falso | Falso | Falso |
| q | Desconocido | Desconocido | Falso | Desconocido |
| | | p | p | p |
| | | Verdadero | Falso | Desconocido |
| q | Verdadero | Verdadero | Verdadero | Verdadero |
| q | Falso | Verdadero | Falso | Desconocido |
| q | Desconocido | Verdadero | Desconocido | Desconocido |
| p | NOT p |
| Verdadero | Falso |
| Falso | Verdadero |
| Desconocido | Desconocido |
| p = q | p = q | p | p | p |
| p = q | p = q | Verdadero | Falso | Desconocido |
| q | Verdadero | Verdadero | Falso | Desconocido |
| q | Falso | Falso | Verdadero | Desconocido |
| q | Desconocido | Desconocido | Desconocido | Desconocido |

Las comparaciones operarias básicas en SQL resultan Desconocidas comparando cualquier cosa con Null, luego el estándar de SQL estipula cálculos predicados cotejados especiales para las dos funciones específicas Null.

El test ES NULL y NO ES NULL determina si el dato es, o no es, Null.

## Tipos de datos

Null no está diseñado como un número entero, carácter u otro tipo de dato específico. Debido a esto, es a veces deseable convertir explícitamente Null en un tipo de dato específico. Por ejemplo, si las funciones sobrecargadas son sostenidas por el SGBD (Sistema de Gestión de Base de Datos), SQL quizás no podría ser capaz de decidir la función correcta sin conocer los tipos de datos de todos los parámetros, incluidos aquellos para los cuales Null ha actuado.

## Lenguaje de manipulación de datos

Los valores lógicos ternarios de SQL se encuentran en el Lenguaje de Manipulación de Datos (LMD) en comparaciones predicadas de afirmaciones LMD y dudas frecuentes. La proposición WHERE (DONDE) propicia que la declaración LMD actúe sólo en aquellas filas para las cuales los cálculos de predicados evalúan la Verdad. Las filas para las cuales estos cálculos evalúan si son Falsas o Desconocidas no derivan de declaraciones DML como INSERT, UPDATE o DELETE, y son desechados a partir de preguntas SELECT. Interpretando Desconocido y Falso como el mismo resultado lógico es un error común encontrado cuando tratamos con Nulls. El siguiente ejemplo lo demuestra:

El ejemplo arriba planteado siempre devuelve lógicamente ceros a las filas debido a que la comparación entre la columna i con Null siempre devuelve un valor Desconocido, incluso para aquellas filas en las que i es Null. El resultado Desconocido causa la declaración SELECT para desechar todas y cada una de las filas (De todas formas, en la práctica, las herramientas SQL recuperarán las filas utilizando la comparación con Null).

## Expresiones CASE

Las expresiones CASE de SQL funcionan conforme a las mismas reglas que las del DMS WHERE para Null. Debido a que puede ser evaluado como una serie de condiciones de comparación de igualdad, una expresión de CASE simple no puede comprobar la existencia de Null directamente. Una comprobación de la existencia de Null en una expresión CASE simple siempre resulta Desconocida, como a continuación:

Como la expresión i = NULL evalúa a Desconocido sin importar el valor que la columna i contenga (incluso si contiene el Null), el resultado ' ES NULL ' nunca será devuelto. Una expresión de CASE buscada también devuelve el primer valor para el cual el resultado de la comparación predicada evalúa la Verdad, incluyendo comparaciones predicadas que usan el “ES NULL” Y “NO ES NULL”. El ejemplo siguiente muestra cómo usar una expresión CASE buscada para comprobar el Null:

En la expresión CASE buscada, ' el Resultado Null ' es devuelta para todas las filas en las cuales i es Null.

## Revisión de las limitaciones

El lugar primario en el cual la lógica ternaria SQL se entrecruza con la Lengua de Definición de Datos SQL (DDL) es en forma de revisión de las limitaciones. Una revisión o comprobación de las limitaciones colocada sobre una columna opera bajo una serie de reglas ligeramente diferentes de aquellas para la cláusula DML WHERE. Mientras que una cláusula DML WHERE debe evaluar la Verdad para una fila, una comprobación no debe evaluar la Falsedad. Esto quiere decir que una revisión tendrá éxito si el resultado de la comprobación es Verdadero o Desconocido. El ejemplo siguiente muestra una tabla con una comprobación que prohibirá a cualquier valor de número entero ser insertado en la columna i, pero permitirá a la Null ser insertada ya que el resultado de la comprobación siempre evaluará si es Desconocido para la Null.

Con el objetivo de que una columna rechace Nulls, la coacción NOT NULL puede ser aplicada, como abajo se muestra en el ejemplo. La coacción NOT NULL es semánticamente equivalente a una comprobación de las limitaciones con un predicado IS NOT NULL.

## Extensiones de procedimientos

SQL/PSM (SQL Módulos Persistentes Almacenados) define extensiones procesales para SQL, como la declaración IF. Sin embargo, las principales comercializaciones de SQL, históricamente han incluido sus extensiones procesales propias. Las extensiones procesales para la formación de bucles y comparaciones funcionan bajo las reglas de comparación Null, similares a las declaraciones DML e interrogaciones. El siguiente fragmento de código, en formato estándar ISO SQL, demuestra el empleo del Null 3VL en una declaración IF.

La declaración IF realiza acciones sólo para aquellas comparaciones que evalúan la Verdad. Para las declaraciones que evalúan la Falsedad o Desconocimiento, la declaración IF pasa el control de la cláusula ELSEIF, y finalmente la cláusula ELSE. El resultado de éste código, siempre será el mensaje 'Resultado es Desconocido' ya que las comparaciones con Null siempre evalúan el Desconocimiento.

## Sentencias JOIN

La sentencia JOIN en SQL permite la combinación de registros de dos o más tablas dentro de una misma base de datos relacional. En SQL existen tres tipos de JOIN: interno, externo, y cruzado. Las sentencias JOIN externas (Outer Joins), incluyendo las de tabla izquierda, derecha y de combinación completa, automáticamente producen Nulls como marcadores (placeholders) de para los valores que faltan en tablas relacionadas. Para combinaciones externas de tabla izquierda, por ejemplo, los Nulls son producidos en lugar de las filas ausentes de la tabla apareciendo en el lado derecho del operador JOIN externo de tabla izquierda. El siguiente ejemplo utiliza dos tablas para demostrar que la producción del marcador Null en la combinación externa izquierda. La primera tabla (Empleado) contiene los números y nombres del empleado ID, mientras la segunda tabla (Número de teléfono) contiene números de teléfono relacionados con el empleado ID, como se muestra abajo.

Empleado :

| Empleado ID Apellido Nombre 1 Izquierdo Roberto 2 Ambrosio Alberto 3 Alfonso Katia 4 Barbadillo Guillermo | Número de teléfono ID Número 1 555-2323 3 555-9876 |
| - | - |

La siguiente muestra SQL desarrolla una combinación externa de tabla izquierda entre las dos tablas anteriores.

El resultado generado en esta serie de cuestiones demuestra cómo SQL usa el Null como un marcador para valores que faltan en la parte derecha de la tabla (Números de teléfono), como se muestra a continuación:

Las combinaciones internas (Inner Joins) y las cruzadas (Cross Joins), también están disponibles en el estándar SQL, y no generan marcadores Null para valores ausentes en tablas relacionadas.

Es necesario tener cuidado a la hora de utilizar columnas en las que pueda operar Null en criterios de unificación de SQL. Como un Null no es igual a ninguna otro Null, los Nulls que se encuentren en una columna de una tabla no se unirán a Nulls de columnas relacionadas de otra tabla que usa los operadores de comparación de igualdad estándar. La función SQL COALESCE o expresiones CASE pueden ser usadas para "simular" una igualdad Null en criterios de unificación, y los predicados ‘ES NULO’ Y ‘NO ES NULL’ pueden ser utilizados en los criterios de unificación también.

El predicado siguiente prueba para la igualdad de los valores A y B y trata a Null como si fuera igual. Se requiere el operador IFNULL ya que A = B devuelve un valor Null si al menos uno de los valores (A o B) es Null y NULL O FALSO es Nulo en sí mismo.

## Concadenación matemática y de caracteres

Como Null no es un valor de datos, pero un marcador para un valor desconocido, usando operadores matemáticos sobre Null resulta un valor desconocido, que es representado por Null. En el ejemplo siguiente, multiplicando 10 por Null resulta Null:

Esto puede conducir a resultados inesperados. Por ejemplo, cuando una tentativa es hecha para dividir Null entre cero, las plataformas pueden devolver Null en vez de lanzar una esperado "excepción de datos - la división entre cero". Aunque este comportamiento no sea definido por la estándar SQL ISO muchos productos comercializados DBMS tratan esta operación de modo similar. Por ejemplo, las plataformas Oracle, PostgreSQL, MySQL Server, y Microsoft SQL Server devuelven el resultado Null para la operación:

La serie de operaciones concadenadas, que son comunes en SQL, también resultan Null cuando uno de los operándos es Null. El siguiente ejemplo demuestra el resultado Null devuelto por el uso de Null con el SQL operador de una serie concadenada.

Esto no es verdadero para todas las puestas en práctica de base de datos. En Oracle RDBMS por ejemplo NULL y serie vacía son consideradas la misma cosa y por lo tanto ‘ Tortilla ‘ la NULL ‘Patata’ resulta ‘Tortilla Patata’.

## Funciones agregadas

SQL define las funciones agregadas para simplificar cálculos agregados de datos del servidor. Casi todas las funciones agregadas realizan un paso de eliminación Null, de modo que los valores Null no sean incluidos en el resultado final del cálculo. Esta eliminación implícita Null, sin embargo, puede influir en los resultados de funciones agregadas. La tabla ejemplificada a continuación deriva resultados diferentes siendo devueltos a cada columna cuando la función agregada SQL AVG (media) es aplicada:

La función agregada SQL AVG devuelve 233 cuando se aplica a la columna i, pero vuelve 175 cuando es aplicado a la columna j. El paso de eliminación de la función agregada Null explica la diferencia en estos resultados. La única función agregada que no elimina implícitamente la Null es la función COUNT.

## Agrupación y clasificación

Como SQL:2003 define todos los marcadores Null como desiguales entre sí, requirieron una definición especial para agrupar las Null en la realización de ciertas operaciones. SQL define "cualquiera de los dos valores que sean iguales el uno al otro, o cualquier pareja de Nulls", como "no distinto". Esta definición de no distinto permite a SQL agrupar y clasificar los Nulls cuando la cláusula GROUP BY (y otras palabras clave que realizan la agrupación) es usada.

Otras operaciones SQL, cláusulas, y palabras clave usan "no distinto" en su tratamiento de Nulls. Estos incluyen lo siguiente:

* La cláusula de clasificación PARTITION BY y funciones de enventanado (windowing) como ROW_NUMBER.
* UNION, INTERSECT y el operador EXCEPT, que tratan los NULLs igual para las determinaciones de comparación/eliminación en filas.
* La palabra clave DISTINCT es usada en preguntas SELECT.
* Coacciones Únicas sobre columnas en las que pueda encontrarse la función Null, que permiten sólo a un valor solo Nulo ser almacenado en la columna.

El estándar SQL no define explícitamente por defecto la clase de orden para los Null. En cambio, sobre sistemas conformados, los Nulls pueden ser clasificados antes o después de todos los valores de datos mediandte el uso de las cláusulas NULLS FIRST o NULLS LAST de la lista ORDER BY, respectivamente. No todos los vendedores de DBMS ponen en práctica esta funcionalidad pese a todo. Los vendedores que no ponen en práctica esta funcionalidad pueden especificar tratamientos diferentes para la clasificación de Null en el DBMS.

## Funciones de tratamiento de Null

SQL define dos funciones para manejar explícitamente la Null: COALESCE y NULLIF. Ambas funciones son abreviaturas para expresiones CASE buscadas.

## COALESCE

La función COALESCE acepta una lista de parámetros, devolviendo el primer valor no Null de la lista:

COALESCE está definida como la siguiente expresión SQL CASE:

Algún DBMSs SQL pone en práctica funciones específicas de vendedor similares para COALESCE. Algunos sistemas ponen en práctica una función de ISNULL, u otras funciones parecidas que son funcionalmente similares a COALESCE.

## NULLIF

La función de NULLIF acepta dos parámetros. Si el primer parámetro es igual al segundo, NULLIF devuelve Null. De otra manera, el valor del primer parámetro es devuelto.

Por lo tanto, NULLIF es una abreviatura de la siguiente expresión CASE:

