I'm a self-taught, vaguely competent SQL user. For a view that I'm writing, I'm trying to develop a 'conditional LEFT
' string-splitting command (presumably later to be joined by a 'conditional RIGHT
' - whereby:
- If a string (let's call it 'haystack') contains a particular pattern (let's call it 'needle'), it will be pruned to the left of that pattern
- Otherwise, the entire string will be passed unaltered.
So, if our pattern is ' - ',
- 'A long string - containing the pattern' will output as 'A long string'
- 'A string without the pattern' will be returned as-is.
Rather than using the crudest ways to do this, I'm trying to come up with a way that avoids having to repeat any clause (such as if 0 < CHARINDEX
, then take CHARINDEX
- 1, etc.) and instead leverages conditional NULL
ing.
Yet - here's what I get for trying to be creative - I've hit what seems to be a really basic stumbling block. Please observe the following code and results, and let me know whether you can replicate it - and hence whether it's a bug or I've missed something peculiar. I have tested this on SQL Server both 2008 R2 and 2014, both Express editions.
select
-- ISNULL: returns 'a big old string'
ISNULL(null, 'a big old string'),
-- NULLIF: returns NULL
left(
'a big old string',
nullif
(
CHARINDEX
(
'needle',
'haystack'
), 0
) - 1
),
-- combined: returns just 'a' (1st character of ISNULL condition)
ISNULL(
left
(
'a big old string', -- the input string. In reality, this would be a column alias, etc.
nullif
(
CHARINDEX -- Search for the splitting pattern
(
'needle',
'haystack'
), 0 -- If it's not found, return NULL instead of the usual 0
) - 1 -- so that this subtraction produces a NULL, not an invalid negative index
),
'a big old string' -- If the pattern was not found, we should return the input unaltered
);
/*
---------------- ---- ----
a big old string NULL a
(1 row(s) affected)
*/
Why do these 2 clauses work as expected in isolation, but when I combine them, rather than getting the sum of their effects, I get only the 1st character of the ISNULL
string - 'a'?
Is there some kind of implicit CAST
to varchar(1)
? Deliberately cast
ing to varchar(max)
made no difference. What else could be going on here?
Am I just doing something really stupid? Because from here, I can't figure out what I'm doing wrong, and so it really seems like a bug. I hoped testing on 2014 would prove it to be a bug in the old 2008 R2, but alas, they act identically (or, rather, don't).
Thanks in advance for, hopefully, saving me from what would presumably be an evening of baffled existential crisis.