Your CASE expression can only have one datatype. But yours is mixing datatypes and the highest one is being used (as per datatype precedence). So nvarchar is changed to int based on these rules.
You need a case per datatype or per column
Example:
CASE WHEN @OrderDirection = 'DESC' THEN
CASE
WHEN @OrderBy = 'JobNumber' THEN J.JobNumber
WHEN @OrderBy = 'CustID' THEN J.CustID
WHEN @OrderBy = 'DateIn' THEN J.DateIn
WHEN @OrderBy = 'DateDue' THEN J.DateDue
WHEN @OrderBy = 'DateOut' THEN J.DateOut
WHEN @OrderBy = 'Status' THEN J.MasterJobStatusID
ELSE NULL
END
END DESC,
CASE WHEN @OrderDirection = 'DESC' THEN
CASE
WHEN @OrderBy = 'OrderNumber' THEN J.OrderNumber
ELSE NULL
END
END DESC
Write your query this way. It includes a better test for integers and dumps ISNUMERIC that returns 1 for '-.', for example.
SELECT
zip,
coordinates
FROM (
SELECT
CASE WHEN ZIP5>'' AND NOT ZIP5 LIKE '%[^0-9]%' THEN
CONVERT(int, [ZIP5]) END zip,
CONVERT(varchar(max), geom) AS coordinates
FROM
[SpatialData].[dbo].[zip5]
WHERE
ZIP5>'' AND NOT ZIP5 LIKE '%[^0-9]%'
) AS t1
WHERE
zip >= 85000 AND
zip < 86000
See this Connect item
SQL Server is free to evaluate the WHERE/SELECT clause in the order that it decides is optimized. A view or derived table is not materialized can easily be expanded into, from the outer query.
What SQL Server is compiling is really a query that looks like this
SELECT
CONVERT(int, [ZIP5]) AS zip,
CONVERT(varchar(max), geom) AS coordinates
FROM
[SpatialData].[dbo].[zip5]
WHERE
ISNUMERIC([ZIP5]) = 1
AND CONVERT(int, [ZIP5]) >= 85000
AND CONVERT(int, [ZIP5]) < 86000
You can inspect the query plan of your original, but my guess from looking at the structure is that the WHERE clause uses the expression CONVERT(int, [ZIP5])
twice, so it makes sense to streamline the resolution (calculation to a result) of the expression in the process of retrieving data from the table. This puts the processing of the SELECT clause before the WHERE, so your ISNUMERIC() = 1
never got a chance to filter the bad eggs.
It is by-design
.
Best Answer
You are not explaining very well what you mean by import (whether it is an insert or an update or a little bit of both), so it is hard to suggest a close enough prototype query for you to use directly or with minimal tweaking. However, the key issue, as I understand it, is to convert each
nvarchar(10)
value ofBOND.MOODYS_RATING
to a correspondingint
key, looking up each string inValidCreditRatings.CreditRating
and taking the key fromValidCreditRatings.KeyValidCreditRatings
.That operation takes a simple inner join:
The
KeyValidCreditRatings
column in the output of this query will contain the values that you can write toLCDOffering.KeyValidCreditRatingsMoody
.A join can be used both in an
UPDATE
statement and in anINSERT
statement (theINSERT ... SELECT
variation). Use the join in the above example query as a basis for the actual query that will be importing data, adding other filters and/or joins as necessary and putting thevcr.KeyValidCreditRatings
reference where the source forLCDOffering.KeyValidCreditRatingsMoody
should go. By the latter I mean, if for instance, yours is anUPDATE
statement, then you will probably have in theSET
clause an assignment like this:And if it is an
INSERT ... SELECT
statement, then you will havevcr.KeyValidCreditRatings
in the select list at the position corresponding to theKeyValidCreditRatingsMoody
column's position in the target column list: