It's also important to understand that there are consequences of each 0 and NULL.
For instance, stricly speaking, the following query should always return 0 rows:
select * from anytable where somefield=NULL;
Why? Because no two NULLS are considered equal. So, the proper syntax to retrieve all rows with nulls in them is:
select * from anytable where somefield IS NULL;
Notice the symantic difference here. IS NOT NULL is the opposite.
Also, NULLS always sort at the top or bottom of a set, and that position may or may not change based on a DESC in the order by, and this is completely legal per the SQL spec, I believe. It's implementation dependent.
Now, here's a thought exercise. What's the exact national debt? Don't know? Then that's a NULL. I can assure you, the national debt is NOT ZERO!
So, programmatically, they are different. Note that most, if not all, database layers in php have a xxx_field_is_null function available to them, so there IS A DIFFERENCE there too, if you care to pay attention to it.
Sadly, both MySQL's and Oracle's rather retarded handling of NULLs has led a whole generation of both experienced, knowledgeable DBAs and newbies all believing that NULL = "" = 0 = DEFAULT etc...
It's not any of those things, and it's kind of funny that MySQL has been busy fixing all their idiosyncracies about NULL, while Oracle happily rolls along thinking NULL = ""