views:

626

answers:

6

Apparently oracle doesn't seem to distinguish between empty strings and nulls. E.g.

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

I can't think of any good reason why Oracle would be built to behave this way (does it do this in sqlplus as well?-I'm accessing through a java interface, the article referenced used a php client).

Wouldn't you at least want to distinguish 0 length from undefined length? Is this a known issue? Intentional behavior for some specific purpose? A long-running dispute in database theory? What gives?

(This was prompted by Matt Solnit's answer to this question.)

+17  A: 
Quassnoi
The only reason is historical? And not fixed for 25 years? How could that be, given that it costs so much? ;)
Steve B.
Cost != quality. I have never used Oracle, but check out Lotus Notes. That software also costs a lot of $$$, but few people would say that it is a high quality application.
Ed Swangren
+1 "waiting for the last person to die"... I can just picture it...
Steve B.
@Steve It's an issue of backward compatibility. This behaviour brings some problems for new development, but changing it to null != empty string would bring thousands times more problems with code suddenly not functioning properly after upgrade to a new Oracle version.
Michal Pravda
excellent explanation.
Mark Harrison
A: 

Looks like Oracle have said that this behaviour may be change in a future release. When and which release it will be is not mentioned.

If you have access to metalink look at note: 1011340.6 (unfortunately because of restrictions I am unable to copy the contents of the note here)

If you don't have access to metalink then look look at the following from the 10g release 2 documentation here

carpenteri
A: 

Just because it's expensive doesn't mean it's not stinky.

Triggers in Oracle can not reference the table they are created on.

Triggers in Oracle CAN NOT reference the table they are created on.

Don't believe me? Try it. It's one of the most common use cases for a trigger. On insert, see if a record already exists, do something based on that fact. No can do in Oracle without bizarre workarounds.

EDIT: My bad (I guess) I was doing an update on the same table and believed what I read, which was that no reference to underlying table was allowed. Again, not some bizarre corner case, but a normal thing to do in a trigger. It does open up a world of recursion in triggers, but that's the programmer's problem.

Ian
-1 because consistency would be seriously harmed if Oracle did allow such thing. And your example would be met by creating a unique constraint, not by implementing buggy trigger code.
Rob van Wijk
Yes you can, see my reply.
tuinstoel
+1  A: 

You might want to read this lenghty and at times funny discussion about this exact subject more than two years ago on OTN: http://forums.oracle.com/forums/thread.jspa?threadID=456874&start=0&tstart=0

Regards, Rob.

Rob van Wijk
Nice discussion!
Quassnoi
A: 

@Ian, a reply to you.

Oracle triggers can reference the table they are created on:

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
tuinstoel
@tuinstoel: only because you are using the VALUES clause. If you switch to the INSERT SELECT:SQL> insert into t select 20 from dual;insert into t select 20 from dual *ERROR at line 1:ORA-04091: table RWIJK.T is mutating, trigger/function may not see itORA-06512: at "RWIJK.T_BIR", line 4ORA-04088: error during execution of trigger 'RWIJK.T_BIR'
Rob van Wijk
-------- I know.
tuinstoel
A: 

Which is why smart people like Date say that you should NEVER use nulls.

(No, I have to be precise. It's in fact only just a single one of the almost hundreds of reasons he has mentioned over this past few decades to support that claim.)

EDIT

I actually also wanted to respond to this :

"Making VARCHAR to do such a distinction will break tons of code."

Yeah, and surely, breaking at least the spirit of the standard by replacing the "empty string" by null on every update is a lesser evil ?

(Note : null is not equal to anything, not even itself, so after assigning the empty string to a column, oracle will give you a value in that column that is NOT the same as the value that you said you wanted to appear there. Wow.)