Monday, April 27, 2009

Stupid SQL, Second Edition - handling the empty string

So it turns out that Oracle has a unique flaw among databases. It treats the empty string exactly as if it were a NULL field. So, for instance, the relation '' = '' is actually false much in the same way that NULL is not equal to NULL.

I've seen some question the utility of empty strings at all, but I ran into this today entirely by accident. I had two tables, both with identical "Path" and "Language" columns, and I wanted to join them. In its simplest form, the query looked like this:

select * from TexturesA
left join TexturesB on TexturesA.Path = TexturesB.Path and TexturesA.Language = TexturesB.Language

Now, as luck would have it, we used an empty string to denote "all languages." This caused the join to fail for any all-languages texture asset, because the equality check on language would fail.

Solution? There are a couple, but I ended up with this gem:

select * from TexturesA
left join TexturesB on TexturesA.Path = TexturesB.Path and TexturesA.Language || '~' = TexturesB.Language || '~'

Not my proudest moment. Works great in practice, though. I suspect that this would keep Oracle from leveraging any indices on the column; if indices are critical, you could probably do the more long-winded:

select * from TexturesA
left join TexturesB on TexturesA.Path = TexturesB.Path and ((TexturesA.Language is null and TexturesB.language is null) or (TexturesA.Language = TexturesB.Language))

Or you could add a function-based index of Language || '~' to the table. Either way, feels like a kludge to me.

No comments:

Post a Comment