Conversion failed when converting the varchar value 'ADMIN' to data type int - sql

I have sql like below. Home hints:
Results in K table (from WITH) gives number codes of specified range (ex.: 1-90).
The main select part works fine until I use
sum(F._IsInIntersection) [CountIntersection]
It causes error
Msg 245, Level 16, State 1, Line 11
Conversion failed when converting the varchar value 'ADMIN' to data type int.
If I comment this line, it is OK.
I do not know, why this error occurs the line with SUM() contains only int values. No ADMIN value (as mentioned in the error) exists anywhere...
Can anyone see any problems with the query?
;with K as (
select cast(c.Code as int) code
from rmCategory c, rmCategoryGroup cg, rmIdentification ic
where 1=1
and c.CategoryGroupID=cg.ID
and c.ID=ic.ID0
)
select
F.STAV_AKT [Code]
, count(F.STAV_AKT) [Count]
, sum(F._IsInIntersection) [CountIntersection]
from
(
select
f.*
, case when f.KVALIF IN (select code from K) and f.KVALIF is not null then 1 else 0 end _IsInIntersection
from frmFormData_208629_MaMo2_IMPORT f, rmIdentification i
where 1=1
and f.ID=i.id0
and i.isValid=1
and f.sysDAVKA=5
) F
group by F.STAV_AKT
order by F.STAV_AKT
I also tried CASTing parameter inside of sum(cast(F._IsInIntersection as int)) [CountIntersection] to be sure to use int values instead of the boolean ones, but no change.

Martin, I'm suspecting that c.Code also contains the value 'ADMIN' in the part
cast(c.Code as int) code
It runs good without the SUM because it's part of a CTE and is not materialized when the column is not used.
If for example I run the following code example in Fiddle it runs fine, but if I also select the column Code it fails when trying to CAST 'ADMIN' to INT (Fiddle).
;WITH cte as
(
select CAST(a AS INT) AS Code
,'Dummy' AS Column2
FROM (
SELECT 1 AS a
UNION ALL SELECT 'a'
) t
)
SELECT Column2
--,Code
FROM cte
So try to figure out what exactly the values for column Code are by using e.g.
SELECT DISTINCT Code FROM rmCategory

What is the datatype of f.sysDAVKA?
Try running
SELECT f.sysDAVKA
FROM frmFormData_208629_MaMo2_IMPORT f
WHERE f.sysDAVKA = 'ADMIN'
My gut feeling is you will find at least one row. If this is true, then changing your WHERE clause to
where 1=1
and f.ID=i.id0
and i.isValid=1
and f.sysDAVKA=CAST(5 AS char(1))
should resolve the problem.

Related

Extracting value from JSON string provokes error message T-SQL

Situation:
I am trying to join a table with ids to another table with ids and a column that is stored in base64 value. I decoded it and used JSON functions to extract a value from key 'a' of the JSON string. I got the famous error message:
JSON text is not properly formatted. Unexpected character '(' is found at position 1.
After browsing similar mistakes online, i added the ISJSON() > 0 as it should exclude the error message - but it didn't.
SELECT
u.ids,
base2.ExtractedValue
FROM #ids AS u
INNER JOIN (
SELECT base.Ids, JSON_VALUE(base.Base64Decoded, '$.a') as ExtractedValue
FROM (
SELECT
ids,
convert(
varchar(MAX),
CAST('' AS xml).value('xs:base64Binary(sql:column("value"))', 'VARBINARY(MAX)')
) AS Base64Decoded
FROM base64info
) AS base
WHERE ISJSON(base.Base64Decoded) > 0
AND base.Base64Decoded is not null
) AS base2 ON u.ids=base2.ids
WHERE base2.ExtractedValue IS NOT NULL
What am it doing wrong?
A case statement solves the issue as such:
CASE WHEN ISJSON(base.Base64Decoded) = 1 THEN JSON_VALUE(base.Base64Decoded, '$.a') END as ExtractedValue

how to convert the output of sub query into numeric

select rptName
from RptTable
where rpt_id in (
select LEFT(Reports, NULLIF(LEN(Reports)-1,-1))
from repoAccess1
where uid = 'VIKRAM'
)
this is my sql query In which i have use the sub query to access selected field
in this sub query returns
select LEFT(Reports, NULLIF(LEN(Reports)-1,-1))
from repoAccess1
where uid = 'VIKRAM'
Returns
1,2
that means the query should be like
select rptName
from RptTable where rpt_id in (1,2)
But i m getting this error
Msg 8114, Level 16, State 5, Line 1
Error converting data type nvarchar to numeric.
could anyone tell me ow to modify to get exact ans
It's a little hard to tell without the concrete table definitions, but I'm pretty sure you're trying to compare different data types to each other. If this is the case you can make use of the CAST or the CONVERT function, for example:
SELECT
[rptName]
FROM [RptTable]
WHERE [rpt_id] IN
(
SELECT
CONVERT(int, LEFT([Reports], NULLIF(LEN([Reports]) - 1, -1)))
FROM [repoAccess1]
WHERE [uid] = 'VIKRAM'
)
UPDATE: Since you have updated your question: The LEFT function returns results of either varchar or nvarchar data type. So the resulting query would be
SELECT
[rptName]
FROM [RptTable]
WHERE [rpt_id] IN('1', '2')
Please note the apostrophes (is this the correct term?) around the values. Since [rpt_id] seems to be of data type int the values cannot implicitly be converted. And that's where the aforementioned CAST or CONVERT come into play.
If I understand correctly, the subquery is returning a single row with a value of '1,2'. This is not a number, hence the error.
Before continuing, let me emphasize that storing values in comma delimited string is not the SQL-way of doing things. You should have one row per id, with proper types and foreign keys defined.
That said, sometimes we are stuck with other people's really bad design decisions. If this is the case, you can use LIKE:
select rptName
from RptTable r
where exists (select 1
from repoAccess1 a
where a.uid = 'VIKRAM' and
',' + a.reports + ',' like '%,' + cast(r.rpt_id as varchar(255)) + ',%'
);
select rptName
from RptTable
where rpt_id in (
select CAST(LEFT(Reports, NULLIF(LEN(Reports)-1,-1)) AS INT) as Val
from repoAccess1
where uid = 'VIKRAM'
)
Your query would work fine when (LEFT(Reports, NULLIF(LEN(Reports)-1,-1)) ) returns either 1 or 2 since SQL Server implicitly converts the varchar value to numeric.
It seems there might be a data issue. One of the data returned by LEFT function is non-numeric. In order to find that particular record you can use isnumeric function. Try like this,
SELECT rptName
FROM RptTable
WHERE rpt_id IN (
SELECT LEFT(Reports, NULLIF(LEN(Reports) - 1, - 1))
FROM repoAccess1
WHERE uid = 'VIKRAM'
AND ISNUMERIC(LEFT(Reports, NULLIF(LEN(Reports) - 1, - 1))) = 1
)

Selecting varchar values from a column

I'm working on SQL 2008 and have a table with 1000's of codes in it - a sample would be:
D37
D37.0
D38
D38.0
D39
D39.0
D3A
D3A.0
D40
What I need to do is select the values between D37 and D40. However, I do not want the D3A values (or D3B or D3C for that matter). I have tried the following:
SELECT Code
FROM Table
WHERE Code BETWEEN 'D37' AND 'D40'
However, this get all the codes listed above, including the D3A codes.
Is there a way to exclude the codes that do not fall in the 37-40 range?
Assuming that the single-letter convention is followed throughout, and there aren't any more weird characters than shown in the data, you can do this:
WITH cte AS (
[MyColumn]
, SELECT SUBSTRING([MyColumn],2,LEN([MyColumn)-1) AS Code
FROM MyTable
WHERE ISNUMERIC(SUBSTRING([MyColumn],2,LEN([MyColumn)-1)=1
)
SELECT [MyColumn]
FROM cte
WHERE CAST(Code AS float) BETWEEN 37 AND 40
It's messy, but this should do what you are asking.
SELECT code
from Mytable
where
ISNUMERIC( SUBSTRING(code, 2, (len(code)) ) ) > 0
and convert(float, SUBSTRING(code, 2, (len(code))) ) between 37 and 40

Convert exponential to number in sql

I have a large amount of card tokens (16 digits) uploaded from xml file to sql-server. The problem is I see them as expression, sample below:
3.3733E+15
3.3737E+15
3.3737E+15
3.3737E+15
3.37391E+15
3.37391E+15
3.37398E+15
3.37453E+15
3.37468E+15
3.37468E+15
3.3747E+15
3.37486E+15
3.37486E+15
3.37567E+15
3.3759E+15
3.3759E+15
Any suggestion to change them to a 16 digit number? I have tried to change the data type, but got error"Conversion failed when converting the varchar value '3.37201E+15' to data type int"
Thanks for help!
Edit:
#X.L.Ant see my code below. I create this table from another one, which is just purely inserted from xml file. Is this may cause an error because some rows are empty in column TOKEN?
CREATE TABLE MULTICURRENCY_CHECK
(
TOKEN varchar(255)
)
/*Merges all card tokens into 1 column, as in xml they are spread across different columns*/
INSERT INTO MULTICURRENCY_CHECK
(
TOKEN
)
SELECT no FROM gpstransactionsnew2
UNION ALL
SELECT no19 FROM gpstransactionsnew2
UNION ALL
SELECT no68 FROM gpstransactionsnew2
UNION ALL
SELECT no93 FROM gpstransactionsnew2
UNION ALL
SELECT no107 FROM gpstransactionsnew2
UNION ALL
SELECT no121 FROM gpstransactionsnew2
SELECT REPLACE(TOKEN, 'OW1', ' ')
FROM MULTICURRENCY_CHECK
/*Converts exponential expression to number*/
SELECT CONVERT(numeric(16,0), CAST(TOKEN AS FLOAT))
FROM MULTICURRENCY_CHECK
Try to cast your string to float before converting it :
SELECT CONVERT(numeric(16,0), CAST(TOKEN AS FLOAT))
FROM MULTICURRENCY_CHECK
See this fiddle.
I don't know what's the format of those numbers in your XML source, but with the data you provide, you'll end up with 33733 for instance followed by a bunch of zeroes. If you have a bigger precision in your XML, maybe you should tweak your importing settings to keep this precision instead of trying to deal with that in the DB.
EDIT:
Try testing your strings with ISNUMERIC to avoid the casting errors you're getting. Adding a raw output of your column will allow you to check which value fails to convert (i.e. converts to 0).
SELECT TOKEN,
CONVERT(NUMERIC(16, 0), CAST(CASE
WHEN ISNUMERIC(TOKEN) = 1
THEN TOKEN
ELSE 0
END AS FLOAT))
FROM MULTICURRENCY_CHECK
For SQL Server 2012+, use TRY_CONVERT().
The use of ISNUMERIC() in xlecoustillier's edited answer does not protect against conversion failures.
Given the following scenario:
CREATE TABLE test(a varchar(100));
insert into test values ('3.3733E+15'),
('3.3737E+15'),
('3.37391E+30'), --fails conversion. included to demonstrate the nature of TRY_CONVERT().
('3.37398E+15'),
('3.37453E+15'),
('3.37468E+15'),
('3.3747E+15'),
('3.37486E+15'),
('3.37567E+15'),
('3.3759E+15');
SELECT TRY_CONVERT(numeric(16,0), CAST(a AS FLOAT))
FROM test
Results in only valid converted values:
---------------------------------------
3373300000000000
NULL
3373910000000000
3373980000000000
3374530000000000
3374680000000000
3374700000000000
3374860000000000
3375670000000000
3375900000000000
However:
SELECT a,
CONVERT(NUMERIC(16, 0), CAST(CASE
WHEN ISNUMERIC(a) = 1
THEN a
ELSE 0
END AS FLOAT))
FROM test
Fails with:
Conversion failed when converting the varchar value '3.3733E+15' to
data type int.
The issue is that all values in the 'a' column return 1 when passed to the ISNUMERIC() function.
SELECT CASE WHEN ISNUMERIC(a) = 1 THEN 'Yes' ELSE 'No' END as IsValueNumeric
FROM test
Try it on SQLFiddle and/or compare with xlecoustillier's sqlfiddle
SELECT colmn_name || '' FROM table_name
This should work.

Sorting SQL string by first 2 or 3 characters

I have been asked to sort a locations table in ascending order. The data in the table currently looks something like this:
100F01
105B02
10B01
GK1-A01
201E12
20A01
However, when this data is displayed on the screen I want it to sort the numeric results in ascending order and then the string results in alphabetic order. The output should look something like this:
10B01
20A01
100F01
105B02
201E12
GK1-A01
I have tried using the following code
SELECT location FROM freelocations
ORDER BY CAST(SUBSTRING(location, 1, 2) AS INT)
however, as expected, this returns an error message because some locations don't start with a numeric:
Conversion failed when converting the varchar value 'GK' to data type int.
Any ideas or tips will be greatly appreciated
Maybe something like this?
select location
from freelocations
order by
case
when patindex('%[^0-9]%', location) = 1 then 9999999999
else cast(substring(location, 1, patindex('%[^0-9]%', location) - 1) as int)
end,
location
(It's a bit clumsy due to SQL Server lacking a regex replace function)
order by FIELD(string+0,1),string+0
but note that '10e20' will be misinterpreted!
Before casting you should check if the first 2 or 3 characters really are digits:
SELECT
location
FROM
freelocations
ORDER BY
CASE
WHEN location like '[0-9][0-9][0-9]%' THEN cast(substring(location,1,3) AS INT)
WHEN location like '[0-9][0-9]%' THEN cast(substring(location,1,2) AS INT)
ELSE 9999
END
Try this to avoid casting:
SELECT
x,
RIGHT('000' +LEFT (x,patindex('%[^0-9]%',x)-1),3) sort1,
RIGHT (x,LEN(x)-patindex('%[^0-9]%',x)+1) sort2
FROM
(
SELECT '123asdf' x
UNION
SELECT '12asdf'
UNION
SELECT '13asdf'
UNION
SELECT '12zsdf'
) X
ORDER BY sort1 ,sort2