Reputation: 20760
I am observing a strange behaviour. The following code that is related to conversion of a substring of nvarchar
to tinyint
works fine:
DECLARE @s nvarchar(50) = N'Line 1'
DECLARE @n tinyint = SUBSTRING(@s, 6, 10)
SELECT
N'Line 1' AS explicit_nvarchar,
@s AS nvarchar_variable,
SUBSTRING(@s, 6, 10) AS nvarchar_substring
, @n AS tinyint_var_converted_earlier
, CAST(SUBSTRING(@s, 6, 10) AS tinyint) AS cast_sub_var
, CAST(SUBSTRING(N'Line 1', 6, 10) AS tinyint) AS cast_nvarchar_substr
I can observe the following output in the Microsoft SQL Server Management Studio:
.
However, the code that tries to do with the SELECT
from the tables fails if the commented line is uncommented:
Select
[order].[identifier] As [order_identifier],
[plan_data].[starts_on] As [from],
[plan_data].[ends_on] As [to],
[workplace].[identifier] AS line_identifier,
SUBSTRING([workplace].[identifier], 6, 10) AS line_no_str
--, CAST(SUBSTRING([workplace].[identifier], 6, 10) AS int) AS line_no
From
...
With commented line...
but with uncommented line (both for conversion to tinyint
or int
)...
Update: Strange. I have added the last line to the WHERE to check whether all lines
contain the 'Line...
Where
[plan].[identifier] = @lPlanIdentifier And
(
[plan_data].[starts_on] Between @fromUTC And @toUTC Or
[plan_data].[ends_on] Between @fromUTC And @toUTC)
AND LEFT([workplace].[identifier], 4) = N'Line'
... and all of a sudden it works also with the uncommented line. How can I discover what causes the problem?
Update2: I should have followed the Hamlet Hakobyan's answer exactly as it was published. When looking inside the table, I can see:
Upvotes: 2
Views: 218
Reputation: 52645
Whenever you have an error converting a varchar to a number the easiest way to find the data is using IsNumeric
. However IsNumeric
doesn't mean IsInteger
so its worth removing scientific or decimal formats as described by G Mastros in this answer
SELECT
[order].[identifier] As [order_identifier],
[plan_data].[starts_on] As [from],
[plan_data].[ends_on] As [to],
[workplace].[identifier] AS line_identifier,
SUBSTRING([workplace].[identifier], 6, 10) AS line_no_str
--, CAST(SUBSTRING([workplace].[identifier], 6, 10) AS int) AS line_no
FROM
...
WHERE
IsNumeric(SUBSTRING([workplace].[identifier], 6, 10) + '.0e0') = 0
If you can't fix it but you can use a default value than you could use a case statement to do the conversion only when its legal to do so.
SELECT
[order].[identifier] As [order_identifier],
[plan_data].[starts_on] As [from],
[plan_data].[ends_on] As [to],
[workplace].[identifier] AS line_identifier,
CASE WHEN IsNumeric(SUBSTRING([workplace].[identifier], 6, 10) + '.0e0') = 1
THEN CAST(SUBSTRING([workplace].[identifier], 6, 10) AS int)
ELSE Null --Default to null in this example
END as line_no
Upvotes: 1
Reputation: 22184
As indicated by the comments and other answer(s), you have a value in [workplace].[identifier]
for one or more rows that fails to cast to an INT
. When you added the following to the WHERE
clause, you eliminated the row(s) that has this data before it was converted in the SELECT
clause:
LEFT([workplace].[identifier], 4) = N'Line'
Run the following to get a distinct list of values in [workplace].[identifier]
SELECT DISTINCT [workplace].[identifier]
FROM [workplace]
Upvotes: 1
Reputation: 33381
You have value in identifier
column for which SUBSTRING([workplace].[identifier], 6, 10)
returns ined
.
Try this query:
SELECT * FROM [workplace]
WHERE SUBSTRING([identifier], 6, 10) = N'ined'
Upvotes: 4