One, nulls lead you into the realm of some 3-valued logic. "Some" logic, because there can be many (one of the possible differences is how logical implication is defined exactly). Anyhow, whatever particular 3VL is used, it will always hold some nasty surprises and be a bit unintuitive at best, or be downright completely unintelligible at worst.
Lots of equivalences (/tautologies) that hold in 2VL, cannot be upheld, or only with great difficulty, in most 3VLs. Take logical implication : in 2VL, it is commonly known that 'p implies q' is equivalent to 'NOT(p) OR q'. You might try to figure out how some very basic tautologies from classical 2VL work out in 3VL.
e.g. p=>q <=> not(q)=>not(p)
or
p or not(p) <=> true
or
p and not(p) <=> false.
Second, there is the mostly adhoc way in which SQL deals with nulls in various circumstances. Add two numbers, one of which is null, and you get null for a result. Do the same using some form of SUM() (using the same arguments), and you get the number zero ! Insert a zero-length string in an Oracle DB and it will convert that to a null, but other DBMS might not do that (I don't know whether equality comparisons comparing some CHAR column to a zero-length string (not necessarily a literal, mind you) behave correctly.
Third, one must remember that nulls, which are essentially boolean flags indicating presence/absence, ADD complexity to query writing, but most of that complexity is swept under the carpet by the SQL language, because it offers lots of "default behaviours" (e.g.comparisons returning FALSE when the real result should be UNKNOWN), thus leaving the developer with the wrong impression that that additional complexity does not exist, and that the developer doesn't need to care about that additional complexity.