Hi
The database guru most critical of nulls in database theory is C.J.Date. Or at least in the system of three valued logic that SQL does so poorly. As C.J.Date points out that SQL itself is not completely logical but that's another story. So yes, be careful when counting and summing - check the query results.
The best you can say, is that they represent "missing values". We agree.
Now you can attach all kinds of meanings to missing values, just be aware that in theory that is completely open.
In other words there is not supposed to be any specific meaning apart from "missing".
We know that the database can generate nulls when doing queries, but then we also know from the SQL manuals that these missing values are put there to represent the fact that the query engine could not find a matching row. So there is no mystery about the nulls that the engine inserts during query processing, they mean "not matched". SQL has attached a meaning in this case! Luckily we can have the manuals to tell us that.
A value that is mandatory cannot be missing, so it is fair to associate nulls with optional columns. If we dont have a value, SHOULD we use a null? That is the question.
Here is a simple case involving numbers. Suppose we have a rating scale -2 -1 0 1 2. If this was a Likert scale, -2 might mean "strongly disagree" and the zero might mean "neither agree nor diagree". It would obviously be wrong to use the value zero when we dont have a rating.
There are two solutions to this problem.
A denormalised "solution" is to attach a status column to the row, that carries the meta-data about the rating. There could be one, or a whole bunch of status reasons why the value was missing. Then it would not matter what value was carried in the rating, the meta-data is available in the status column. Ideally some sort of "set-valued" datatype would do nicely. (Is this denormalised? You could argue that the metadata in the status column is in fact about the meaning of the whole row. Its a messy issue, and this is a messy solution anyway.)
The preferred solution is to simply assign a null value and use whatever SQL lets you do to manage them.
That's all very well, but what about strings? Strings have a third competing solution, the empty string! But if we use nulls for missing numbers, then by rights we should use nulls for missing strings. Some databases simply enforce that. We should view the empty string in the same light as we viewed our zero rating value.
So then do we avoid empty strings altogether?
Well no. Just as we can attach meanings to zero, we can attach meanings to the empty string.
Suppose we have a customer who submits a web form.
You know for sure that they have been given the opportunity to comment. But the comment arrives at the server empty. The user has exercised their right to not comment.
And what if some of the existing rows have been obtained from another table using an outer join, with missing comments as nulls because the users of that database were simply not invited to comment.
The empty string is an opportunity here - it is tempting to capture additional semantics with empty strings to represent "no comment" metadata in this instance, with particular semantics. Fair enough. That doesn't conflict with the use of nulls.
So IMHO the long and the short of it is, that whatever your design means, try to avoid using nulls, let alone empty strings. When you use nulls, avoid attaching meanings.
And if you are using internal meanings at all, given the world is not ideal, then document them. Caveat emptor.