2009-08-12 7 views
14

Apparemment, l'oracle ne semble pas faire la distinction entre les chaînes vides et les valeurs nulles. Par exemple.Oracle ne fait pas de distinction entre les valeurs nulles et les chaînes vides?

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 

Je ne peux pas penser à une bonne raison pour laquelle Oracle serait construit pour se comporter de cette façon (fait-elle cela dans sqlplus aussi? -Je suis accès via une interface java, l'article référencé utilisé une client php). Vous ne voulez pas au moins distinguer 0 longueur d'une longueur indéfinie?

est-ce un problème connu? Comportement intentionnel dans un but précis? Un conflit de longue date dans la théorie des bases de données? Ce qui donne?

(Cette demande a été la réponse à this question Matt Solnit.)

+0

Cette question a été postée comme étant liée, bien qu'elle n'aborde pas le "pourquoi": http://stackoverflow.com/questions/1171196/difference-between-varchar-and-varchar2 –

Répondre

33

Oracle est très très très vieux.

Retour à 80's quand il a été développé (et avant il y avait des normes), ils pensaient que c'était une bonne idée, et donné alors Oracle stocke ses valeurs, il l'était vraiment.

Voilà comment données Oracle magasins (prises du documentation):

alt text

Aucun type de données sont stockées dans les données, seule la longueur des données et les données elles-mêmes.

Si le NULL se produit entre deux colonnes avec des valeurs, il est stocké sous la forme d'un octet, ce qui signifie que la colonne a une longueur de 0 (actuellement, 0xFF). Les suivis NULL ne sont pas stockés du tout. Donc, pour stocker la valeur 'test', Oracle doit stocker 5 octets: 04 74 65 73 74. Toutefois, pour stocker à la fois une chaîne vide et un NULL, Oracle doit juste définir la longueur de données sur 0.

Très intelligent si vos données doivent être stockées sur 20 Mb disques durs qui coûtent 5,000$ chacun. Plus tard, lorsque les normes sont apparues, ce n'était plus une bonne idée, mais à cette époque, il y avait déjà beaucoup de code qui s'appuyait sur NULL et '' étant la même chose.

Faire VARCHAR pour faire une telle distinction va casser tonnes de code.

Pour résoudre ce problème, ils rebaptisés VARCHAR-VARCHAR2 (qui ne fait pas partie d'une norme), a déclaré que VARCHAR2 sera jamais la distinction entre un NULL et une chaîne vide et a exhorté tout le monde à utiliser ce type de données à la place.

Maintenant, ils attendent probablement la dernière personne qui a utilisé un VARCHAR dans la base de données Oracle pour mourir.

+0

La seule raison est historique? Et pas fixé pour 25 ans? Comment cela pourrait-il être, étant donné que cela coûte tellement cher? ;) –

+2

Coût! = Qualité. Je n'ai jamais utilisé Oracle, mais consultez Lotus Notes. Ce logiciel coûte aussi beaucoup de $$$, mais peu de gens diraient que c'est une application de haute qualité. –

+3

+1 "attente de la dernière personne à mourir" ... Je peux juste l'imaginer ... –

0

On dirait qu'Oracle a dit que ce comportement pourrait changer dans une prochaine version.Quand et quel communiqué il sera n'est pas mentionné.

Si vous avez accès à regarder metalink à la note: 1.011.340,6 (malheureusement, à cause des restrictions que je suis incapable de copier le contenu de la note ici)

Si vous n'avez pas accès à metalink regarder alors regarder la suite de la version 10g 2 documentation here

0

@Ian, une réponse à vous.

Oracle déclencheurs peuvent faire référence à la table, ils sont créés sur:

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: seulement parce que vous utilisez la clause VALUES Si vous passez à INSERT SELECT: SQL> insérer dans t sélectionner 20 à partir du dual; insérer dans t sélectionner 20 à partir du double * ERREUR a t ligne 1: ORA-04091: la table RWIJK.T est en mutation, le déclencheur/la fonction peut ne pas le voir ORA-06512: à "RWIJK.T_BIR", ligne 4 ORA-04088: erreur lors de l'exécution du trigger 'RWIJK. T_BIR ' –

+0

-------- Je sais. – tuinstoel

1

Quelle est la raison pour laquelle les gens intelligents comme date disent que vous ne devriez jamais utiliser nulls.

(Non, je dois être précis. Il est en fait juste un seul des quelque centaines de raisons pour lesquelles il a mentionné au cours ces quelques dernières décennies pour soutenir cette affirmation.)

EDIT

En fait, je voulais aussi répondre à cela:

"Faire VARCHAR pour faire une telle distinction va casser des tonnes de code." Ouais, et sûrement, briser au moins l'esprit de la norme en remplaçant la "chaîne vide" par null sur chaque mise à jour est un moindre mal? (Note: null n'est égal à rien, même pas lui-même, donc après avoir assigné la chaîne vide à une colonne, Oracle vous donnera une valeur dans cette colonne qui n'est PAS la même que celle que vous avez voulue pour apparaître là Wow.)

Questions connexes