sql - vacio - ¿Por qué Oracle 9i trata una cadena vacía como NULL?
sql server variable vacia (10)
Sé que se considera " NULL
, pero eso no hace mucho para decirme por qué este es el caso. Como entiendo las especificaciones de SQL, '''' no es lo mismo que NULL
: uno es un dato válido y el otro indica la ausencia de esa misma información.
Siéntase libre de especular, pero por favor indique si ese es el caso. Si hay alguien de Oracle que pueda comentarlo, ¡sería fantástico!
Creo que la respuesta es que Oracle es muy, muy viejo.
En los viejos tiempos antes de que existiera un estándar SQL, Oracle tomó la decisión de diseño de que las cadenas vacías en las columnas VARCHAR
/ VARCHAR2
eran NULL
y que solo había un sentido de NULL (hay teóricos relacionales que diferenciarían entre datos que nunca han sido solicitados, datos donde existe la respuesta pero no son conocidos por el usuario, datos donde no hay respuesta, etc., todos los cuales constituyen algún sentido de NULL
).
En el momento en que llegó el estándar SQL y acordó que NULL
y la cadena vacía eran entidades distintas, ya había usuarios de Oracle que tenían un código que asumía que los dos eran equivalentes. Así que, básicamente, Oracle se quedó con las opciones de romper el código existente, violar el estándar SQL o introducir algún tipo de parámetro de inicialización que cambiaría la funcionalidad de un gran número de consultas. La violación del estándar SQL (IMHO) fue la menos disruptiva de estas tres opciones.
Oracle ha dejado abierta la posibilidad de que el tipo de datos VARCHAR
cambie en una versión futura para cumplir con el estándar SQL (razón por la cual todos usan VARCHAR2
en Oracle, ya que se garantiza que el comportamiento de ese tipo de datos seguirá siendo el mismo).
De hecho, no he tenido más que dificultades al tratar con Oracle, incluidos los valores de fecha y hora no válidos (no se pueden imprimir, convertir ni nada, solo se han visto con la función DUMP ()) que pueden insertarse en la base de datos, aparentemente a través de algún buggy. Versión del cliente como una columna binaria! ¡Tanto para proteger la integridad de la base de datos!
Manejo de Oracle de enlaces NULLs:
http://digitalbush.com/2007/10/27/oracle-9i-null-behavior/
http://jeffkemponoracle.com/2006/02/empty-string-andor-null.html
Ejemplo de libro
set serveroutput on;
DECLARE
empty_varchar2 VARCHAR2(10) := '''';
empty_char CHAR(10) := '''';
BEGIN
IF empty_varchar2 IS NULL THEN
DBMS_OUTPUT.PUT_LINE(''empty_varchar2 is NULL'');
END IF;
IF '''' IS NULL THEN
DBMS_OUTPUT.PUT_LINE('''''''''' is NULL'');
END IF;
IF empty_char IS NULL THEN
DBMS_OUTPUT.PUT_LINE(''empty_char is NULL'');
ELSIF empty_char IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE(''empty_char is NOT NULL'');
END IF;
END;
En primer lugar, las cadenas nulas y nulas no siempre fueron tratadas como iguales por Oracle. Una cadena nula es, por definición, una cadena que no contiene caracteres. Esto no es en absoluto lo mismo que un nulo. NULL es, por definición, la ausencia de datos.
Hace cinco o seis años, la cadena nula fue tratada de manera diferente a la nula por Oracle. Mientras que, como nulo, la cadena nula era igual a todo y diferente de todo (lo que creo que está bien para nulo, pero totalmente INCORRECTO para la cadena nula), al menos la longitud (cadena nula) devolvería 0, como debería, ya que la cadena nula es una cadena de longitud cero.
Actualmente en Oracle, length (null) devuelve null, lo que supongo que está bien, pero length (null string) también devuelve null que es totalmente INCORRECTA.
No entiendo por qué decidieron comenzar a tratar estos 2 "valores" distintos de la misma manera. Significan cosas diferentes y el programador debe tener la capacidad de actuar en cada una de diferentes maneras. El hecho de que hayan cambiado su metodología me dice que realmente no tienen ni idea de cómo deben tratarse estos valores.
La cadena vacía es lo mismo que NULL simplemente porque es el "mal menor" en comparación con la situación cuando las dos (cadena vacía y nula) no son lo mismo.
En los idiomas donde NULL y String vacío no son lo mismo, uno siempre debe verificar ambas condiciones.
La documentación de Oracle alerta a los desarrolladores de este problema y se remonta al menos a la versión 7.
Oracle eligió representar NULLS por la técnica del "valor imposible". Por ejemplo, un NULL en una ubicación numérica se almacenará como "menos cero", un valor imposible. Todos los ceros negativos que resulten de los cálculos se convertirán a cero positivo antes de ser almacenados.
Oracle también eligió, erróneamente, considerar que la cadena VARCHAR de longitud cero (la cadena vacía) es un valor imposible, y una opción adecuada para representar NULL. Resulta que la cadena vacía está lejos de ser un valor imposible. ¡Es incluso la identidad bajo la operación de concatenación de cuerdas!
La documentación de Oracle advierte a los diseñadores y desarrolladores de bases de datos que alguna versión futura de Oracle podría romper esta asociación entre la cadena vacía y NULL, y romper cualquier código que dependa de esa asociación.
Existen técnicas para marcar NULLS que no sean valores imposibles, pero Oracle no los usó.
(Estoy usando la palabra "ubicación" arriba para indicar la intersección de una fila y una columna.)
Porque no tratarlo como NULL tampoco es particularmente útil.
Si comete un error en esta área en Oracle, generalmente se da cuenta de inmediato. Sin embargo, en el servidor SQL parecerá que funciona, y el problema solo aparece cuando alguien ingresa una cadena vacía en lugar de NULL (quizás de una biblioteca de cliente .net, donde null es diferente de "", pero generalmente se trata de la misma manera ).
No estoy diciendo que Oracle tenga razón, pero me parece que ambas formas son aproximadamente igualmente malas.
Sospecho que esto tiene mucho más sentido si piensa en Oracle como probablemente lo hicieron los desarrolladores anteriores, como un backend glorificado para un sistema de entrada de datos. Cada campo en la base de datos correspondía a un campo en una forma que un operador de ingreso de datos vio en su pantalla. Si el operador no escribió nada en un campo, ya sea "fecha de nacimiento" o "dirección", los datos de ese campo son "desconocidos". No hay forma de que un operador indique que la dirección de alguien es realmente una cadena vacía, y eso no tiene mucho sentido de todos modos.
Tom Kyte VP de Oracle:
Una varchar de longitud CERO se trata como NULL.
'''' no se trata como NULL.
'''' cuando se asigna a un char (1) se convierte en '''' (los tipos de caracteres son cadenas rellenadas en blanco).
'''' cuando se asigna a varchar2 (1) se convierte en '''' que es una cadena de longitud cero y una cadena de longitud cero es NULL en Oracle (no es larga '''')
Según los documentos oficiales 11g
Oracle Database actualmente trata un valor de carácter con una longitud de cero como nulo. Sin embargo, esto puede no seguir siendo cierto en futuras versiones, y Oracle recomienda que no trate las cadenas vacías de la misma manera que las nulas.
Posibles razones
-
val IS NOT NULL
es más legible queval != ''''
- No es necesario verificar ambas condiciones
val != '''' and val IS NOT NULL