2009-08-12 6 views
14

Aparentemente Oracle no parece distinguir entre cadenas vacías y valores nulos. P.ej.Oracle no distingue entre nulos y cadenas vacías?

Select name from TABLE_A where id=100; 
    ID NAME 
    100 null 

Update TABLE_A set NAME='' where id=100; 
SELECT --> 
    ID NAME 
    100 null 

SELECT length(NAME) FROM TABLE_A WHERE id=100; 
    null 

No puedo pensar en ninguna buena razón por Oracle se construiría a comportarse de esta manera (es lo que hace esto en sqlplus así? -Estoy acceder a través de una interfaz Java, el artículo de referencia utiliza una cliente php).

¿No querría al menos distinguir la longitud 0 de la longitud indefinida? ¿Es esto un problema conocido? Comportamiento intencional para un propósito específico ¿Una larga disputa en la teoría de bases de datos? ¿Lo que da?

(Esto fue motivado por la respuesta de Matt Solnit a this question.)

+0

Esta pregunta se ha publicado como relacionada, aunque no aborda el "por qué": http://stackoverflow.com/questions/1171196/difference-between-varchar-and-varchar2 –

Respuesta

33

Oracle es muy muy muy vieja.

De vuelta en 80's cuando fue desarrollado (y antes de que existieran las normas) pensaron que era una buena idea, y dado que el modo Oracle almacena sus valores, realmente lo era.

Así es como Oracle almacenes de datos (tomados de la documentation):

alt text

Sin tipo de datos se almacenan dentro de los datos, sólo la longitud de datos y los datos en sí.

Si el NULL se produce entre dos columnas con valores, se almacena como una columna de significado de un solo byte con longitud 0 (en realidad, 0xFF). NULL s seguidos no se almacenan en absoluto.

Para almacenar el valor 'test', Oracle necesita almacenar 5 bytes: 04 74 65 73 74.

Sin embargo, para almacenar tanto una cadena vacía como NULL, Oracle solo necesita establecer la longitud de los datos en 0.

Muy inteligente si sus datos van a almacenarse en discos duros 20 Mb que cuestan 5,000$ cada uno.

Más tarde, cuando aparecieron las normas, ya no era una buena idea, pero en ese momento ya había muchos códigos confiando en que NULL y '' eran lo mismo.

Hacer VARCHAR hacer tal distinción romperá toneladas del código.

Para solucionarlo, se cambió el nombre a VARCHARVARCHAR2 (que no es parte de ningún estándar), declaró que se VARCHAR2Nunca distinguir entre un NULL y una cadena vacía e instó a todos a utilizar este tipo de datos en su lugar.

Ahora probablemente estén esperando a que muera la última persona que usó VARCHAR en la base de datos Oracle.

+0

¿La única razón es histórica? ¿Y no arreglado por 25 años? ¿Cómo podría ser eso, dado que cuesta tanto? ;) –

+2

¡Costo! = Calidad. Nunca he usado Oracle, pero eche un vistazo a Lotus Notes. Ese software también cuesta mucho $$$, pero pocas personas dirían que es una aplicación de alta calidad. –

+3

+1 "esperando a que muera la última persona" ... Puedo imaginarlo ... –

0

Parece que Oracle ha dicho que este comportamiento puede cambiar en una versión futura.Cuándo y qué versión será no se menciona.

Si usted tiene acceso a la mirada metalink en la nota: 1011340.6 (por desgracia, debido a las restricciones no soy capaz de copiar el contenido de la nota aquí)

Si usted no tiene acceso a metalink luego buscar mira el después de la liberación 10g 2 documentación here

0

@Ian, una respuesta para usted.

disparadores de Oracle pueden hacer referencia a la tabla que se crean en:

create table t (id number(10)); 

create or replace trigger t_bir before insert on t for each row 
declare 
    l_id t.id%type; 
begin 
    select id 
    into l_id 
    from t 
    where id = :new.id; 
exception 
    when no_data_found then 
    null; 
end; 
/


SQL> insert into t values (20); 

1 row is created. 


SQL> select * from t; 

     ID 
---------- 
     20 
+0

@tuinstoel: solo porque estás usando la cláusula VALUES. Si cambias a INSERT SELECT: SQL> insertar en t seleccionar 20 desde dual; insertar en t seleccionar 20 desde dual * ERROR a t línea 1: ORA-04091: la tabla RWIJK.T está mutando, el disparador/función puede no verlo ORA-06512: en "RWIJK.T_BIR", línea 4 ORA-04088: error durante la ejecución del disparador 'RWIJK. T_BIR ' –

+0

-------- Lo sé. – tuinstoel

1

Cuál es la razón por la gente inteligente como Fecha dicen que nunca se debe utilizar nulos.

(No, tiene que ser preciso. Es, de hecho, sólo acaba de uno solo de los casi cientos de razones por las que se mencionan más de esta últimas décadas para apoyar esta afirmación.)

EDITAR

De hecho, también quería responder a esto:

"Hacer que VARCHAR haga tal distinción romperá toneladas de código".

Sí, y sin duda, romper al menos el espíritu de la norma mediante la sustitución de la "cadena vacía" por nulo en cada actualización es un mal menor?

(Nota: null no es igual a nada, ni siquiera a sí mismo, así que después de asignar la cadena vacía a una columna, Oracle le dará un valor en esa columna que NO es el mismo que el que dijo que quería para aparecer allí. Wow.)

Cuestiones relacionadas