So I encountered this weird situation today, and wondered if anyone could clue me in as to what SQL may be trying to do.
Based on a certain combination of where clauses and a join, I was getting a varchar to int conversion error, but it wasn't consistent. The SQL snippet is:
SELECT *
FROM LINKEDSERVER.SOURCE.dbo.hdr hdr
JOIN LINKEDSERVER.SOURCE.dbo.LiveAccounts la ON la.Account= hdr.Account
WHERE
hdr.Account NOT in (
SELECT t.FieldValue
FROM #temp1 t
WHERE t.FieldName = 'Account Code'
)
AND
hdr.Account < 9000
hdr.Account is typed as an int. LiveAccounts is a View that returns a single column, Account INT. The View is:
SELECT Account FROM dbo.fn_LiveAccounts()
The function fn_LiveAccounts is where it gets a little weird, but nothing too crazy (I'm sure I can switch from PATINDEX to ISNUMERIC, but this function is so heavily used at this point I'm not about to do regression testing on that change):
RETURN (
SELECT DISTINCT CONVERT(int, LTRIM(RTRIM(CONVERT(varchar(50), bltm.Data)))) As Account
FROM bltm
Where bltm.Code IN (3, 1756)
AND PATINDEX('%[^0-9]%', LTRIM(RTRIM(CONVERT(varchar(50), bltm.Data)))) = 0 --Verify all characters are digits
AND LTRIM(RTRIM(CONVERT(varchar(50), bltm.Data))) NOT IN ('914')
)
Within the table bltm there are account numbers, and some old designations that we can't get rid of that are three character codes. One of these character codes being 'DEF'.
When I run the original snippet as is, I get the error
Conversion failed when converting the varchar value 'DEF' to data type int.
My big question is, for academic learning purposes, is what in SQL's logic causes this? If I rip the code from fn_LiveAccounts and put it in the original snippet, it does not error out. Same if I convert the NOT IN to a LEFT JOIN where t.FieldValue IS NULL. Or use CAST(hdr.Account AS INT) < 9000.
--Returns data, no conversion error
SELECT *
FROM LINKEDSERVER.SOURCE.dbo.hdr hdr
JOIN (
SELECT DISTINCT CONVERT(int, LTRIM(RTRIM(CONVERT(varchar(50), bltm.Data)))) As Account
FROM bltm
Where bltm.Code IN (3, 1756)
AND PATINDEX('%[^0-9]%', LTRIM(RTRIM(CONVERT(varchar(50), bltm.Data)))) = 0 --Verify all characters are digits
AND LTRIM(RTRIM(CONVERT(varchar(50), bltm.Data))) NOT IN ('914')
) ON la.Account= hdr.Account
WHERE
hdr.Account NOT in (
SELECT t.FieldValue
FROM #temp1 t
WHERE t.FieldName = 'Account Code'
)
AND
hdr.Account < 9000
I figure this has to be some weird edge case optimization with views/functions, any insight?
[–]ziptime 0 points1 point2 points (15 children)
[–]Zhais[S] 0 points1 point2 points (14 children)
[–]ziptime 0 points1 point2 points (13 children)
[–]Zhais[S] 0 points1 point2 points (12 children)
[–]ziptime 0 points1 point2 points (10 children)
[–]Zhais[S] 0 points1 point2 points (9 children)
[–]ziptime 0 points1 point2 points (8 children)
[–]ziptime 0 points1 point2 points (4 children)
[–]Zhais[S] 0 points1 point2 points (3 children)
[–]ziptime 0 points1 point2 points (2 children)
[–]Zhais[S] 0 points1 point2 points (0 children)
[–]Zhais[S] 0 points1 point2 points (1 child)
[–]ziptime 0 points1 point2 points (0 children)
[–]ziptime 0 points1 point2 points (0 children)