I have table1 with two columns:
col1 - nvarchar(510)
col2 - nvarchar(510)
I want to take all the values from table1 and put it to table2 where data type is different:
col1_A - numeric(22,10)
col2_A - int
I'm doing like:
insert into table2
select cast(col1 as numeric), cast(col2 as int)
but I'm getting error:
What is wrong?
You probably have a character in table1.col1. Also, it's important to point out that table1.col1 is nvarchar(510) but if len(table1.col1) > 11 you are going to get an Arithmetic overflow error.
declare #char nvarchar(510)
set #char = '123456789101'
--set #char = '1234567891011' --will cause an arithmetic overflow error since you are using numeric(22,10)
--set #char = '123abc456' --will cause Error converting data type nvarchar to numeric
declare #num numeric(22,10)
set #num = cast(#char as numeric(22,10))
select #num
It means you need to sanitize your data. Find which values are causing the issue and then manually correct them first or exclude them. To find which values are not numeric use the ISNUMERIC function.
select col1
from yourtable
where ISNUMERIC(col1) = 0
thank you Eric for help to find wrong recrods!
I did case as below:
case
when [col1] LIKE '%,%' then REPLACE([col1]),',','')
else CAST([col1] as Numeric)
end
and it's working!
Related
I am inserting table A to table B. The problematic column looks like -$25.2. I first replaced the $ and tried insert. Got this error
Error converting data type nvarchar to float.
I then checked by
SELECT *
FROM B
WHERE ISNUMERIC([Col Name]) <> 1
and no results were returned.
This is odd. It is supposed to return something.
What should I check next?
I also tried something like
CAST(REPLACE([Col Name], '-$', '') AS FLOAT)
Try using this
DECLARE #Text nvarchar(100)
SET #Text = '-$1234.567'
SET #Text = Replace(#Text,'$', '')
Select CONVERT(float, #Text) AS ColumnValue
Select ABS(CONVERT(float, #Text)) AS ColumnValue
While the 'money' data type isn't great for doing calculations, in this scenario you can use it as an intermediary.
declare #a nvarchar(10)
set #a = '-$25.2'
select
#a,
cast(cast(#a as money) as float)
Only use this though if your data only goes to a max of 4 decimal places, otherwise you will lose precision in the conversion.
I came across a bug where I was using CAST(Col1 AS INT) + CAST(Col2 AS INT) where both Col1 and Col2 are VARCHAR and I was getting valid results out when Col1 or Col2 was blank and I didn't expect this. I checked and CAST (and CONVERT) both have this default behavior of replacing blank with 0:
SELECT CAST('' AS INT)
SELECT CONVERT(INT, '')
I checked the info page and I can't see any reference to explain why this is the behavior (or change it through a server setting). I can of course work around this but I wanted to ask why this is the behavior as I do not think it is intuitive.
I'd actually rather this CAST failed or gave NULL, is there a server setting somewhere which effects this?
Consider an INT in SQL Server. It can be one of three values:
NULL
0
Not 0
So if you're casting/converting an empty string, which you are assuming is a number, then 0 is the most logical value. It allows for a distinction between NULL and 0.
SELECT CAST(NULL AS INT) -- NULL
SELECT CAST('' AS INT) -- 0
SELECT CAST('42' AS INT) -- 42
I'd say that's logical.
If you did:
SELECT CAST('abc' AS INT)
You'd get:
Conversion failed when converting the varchar value 'abc' to data type int.
If you do wish to handle empty strings as NULL use NULLIF as Bogdan suggests in his answer:
DECLARE #val VARCHAR(2) = ''
SELECT CAST(NULLIF(#val,'') AS INT) -- produces NULL
NULLIF returns the first expression if the two expressions are not equal. If the expressions are equal, NULLIF returns a null value of the type of the first expression.
Finally, if your columns are storing INT values, then consider changing its data type to INT if you can.
As you probably know NULL is a marker that indicates that a data value does not exist. And '' is a value, empty but value.
So MS SQL cast (or converts) empty value into 0 by default. To overcome this and show it as NULL you can use NULLIF
Simple example:
SELECT int_as_varchars as actual,
cast(NULLIF(int_as_varchars,'') as int) as with_nullif,
cast(int_as_varchars as int) as just_cast
FROM (VALUES
('1'),
(''),
(NULL),
('0')
) as t(int_as_varchars)
Output:
actual with_nullif just_cast
1 1 1
NULL 0
NULL NULL NULL
0 0 0
As you see NULLIF in that case will help you to get NULL instead of 0.
What about this ?
declare #t table(bucket bigint);
INSERT INTO #t VALUES (1);
INSERT INTO #t VALUES (2);
INSERT INTO #t VALUES (-1);
INSERT INTO #t VALUES (5);
INSERT INTO #t VALUES (0);
declare #Bucket bigint = 0 --filter by 0
select * from #t
where 1=1
AND ((#Bucket is Null or cast(#Bucket as nvarchar) = '') or bucket=#Bucket)
I have variable called #prmclientcode which is nvarchar. The input to this variable can be a single client code or multiple client codes separated by comma. For e.g.
#prmclientcode='1'
or
#prmclientcode='1,2,3'.
I am comparing this variable to a client code column in of the tables. The data type of this column is numeric(6,0). I tried converting the variable data type like below
SNCA_CLIENT_CODE IN ('''+convert(numeric(6,0),#prmclientcode+''')) (The query is inside a dynamic sql).
But when I try executing this I get the error
Arithmetic overflow error converting nvarchar to data type numeric.
Can anyone please help me here!
Thanks!
You need to convert the numeric(6,0) column to nvarchar data type. You can use below scrip to convert it to nvarchar, before processing:
SNCA_CLIENT_CODE IN ('''+convert(cast( numeric(6,0) as nvarchar(max) ),#prmclientcode+'''))
Please try with the below code snippet.
DECLARE #ProductTotals TABLE
(
ProductID int
)
INSERT INTO #ProductTotals VALUES(1)
INSERT INTO #ProductTotals VALUES(11)
INSERT INTO #ProductTotals VALUES(3)
DECLARE #prmclientcode VARCHAR(MAX)='1'
SELECT * FROM #ProductTotals
SELECT * FROM #ProductTotals WHERE CHARINDEX(',' + CAST(ProductID AS VARCHAR(MAX)) + ',' , ',' + ISNULL(#prmclientcode,ProductID) + ',') > 0
Let me know if any concern.
use following code in order to separate your variable:
DECLARE
#T VARCHAR(100) = '1,2,3,23,342',
#I int = 1
;WITH x(I, num) AS (
SELECT 1, CHARINDEX(',',#T,#I)
UNION ALL
SELECT num+1,CHARINDEX(',',#T,num+1)
FROM x
WHERE num+1<LEN(#T)
AND num<>0
)
SELECT SUBSTRING(#T,I,CASE WHEN num=0 THEN LEN(#T)+1 ELSE num END -I)
FROM x
Use can use either table function or dynamic sql query, both options will work.
Let me know if you need more help
I have a field value productlength of 0.123. This is from a view and has a data type of varchar.
I need to convert it to a float or numeric value so as o perform math comparisons.
convert(float,productlength)
and
cast(productlength as float) both do not work.
error varchar cant be converted to float or somethiing liek that.
From what I have read varchar can simply not be converted to a numeric string?
Any clever ways around this?
You can convert varchars to floats, and you can do it in the manner you have expressed. Your varchar must not be a numeric value. There must be something else in it. You can use IsNumeric to test it. See this:
declare #thing varchar(100)
select #thing = '122.332'
--This returns 1 since it is numeric.
select isnumeric(#thing)
--This converts just fine.
select convert(float,#thing)
select #thing = '122.332.'
--This returns 0 since it is not numeric.
select isnumeric(#thing)
--This convert throws.
select convert(float,#thing)
Use
Try_convert(float,[Value])
See
https://raresql.com/2013/04/26/sql-server-how-to-convert-varchar-to-float/
DECLARE #INPUT VARCHAR(5) = '0.12',#INPUT_1 VARCHAR(5)='0.12x';
select CONVERT(float, #INPUT) YOUR_QUERY ,
case when isnumeric(#INPUT_1)=1 THEN CONVERT(float, #INPUT_1) ELSE 0 END AS YOUR_QUERY_ANSWERED
above will return values
however below query wont work
DECLARE #INPUT VARCHAR(5) = '0.12',#INPUT_1 VARCHAR(5)='0.12x';
select CONVERT(float, #INPUT) YOUR_QUERY ,
case when isnumeric(#INPUT_1)=1 THEN CONVERT(float, #INPUT_1) ELSE **#INPUT_1** END AS YOUR_QUERY_ANSWERED
as #INPUT_1 actually has varchar in it.
So your output column must have a varchar in it.
I am stuck on converting a varchar column UserID to INT. I know, please don't ask why this UserID column was not created as INT initially, long story.
So I tried this, but it doesn't work. and give me an error:
select CAST(userID AS int) from audit
Error:
Conversion failed when converting the varchar value
'1581............................................................................................................................' to data type int.
I did select len(userID) from audit and it returns 128 characters, which are not spaces.
I tried to detect ASCII characters for those trailing after the ID number and ASCII value = 0.
I have also tried LTRIM, RTRIM, and replace char(0) with '', but does not work.
The only way it works when I tell the fixed number of character like this below, but UserID is not always 4 characters.
select CAST(LEFT(userID, 4) AS int) from audit
You could try updating the table to get rid of these characters:
UPDATE dbo.[audit]
SET UserID = REPLACE(UserID, CHAR(0), '')
WHERE CHARINDEX(CHAR(0), UserID) > 0;
But then you'll also need to fix whatever is putting this bad data into the table in the first place. In the meantime perhaps try:
SELECT CONVERT(INT, REPLACE(UserID, CHAR(0), ''))
FROM dbo.[audit];
But that is not a long term solution. Fix the data (and the data type while you're at it). If you can't fix the data type immediately, then you can quickly find the culprit by adding a check constraint:
ALTER TABLE dbo.[audit]
ADD CONSTRAINT do_not_allow_stupid_data
CHECK (CHARINDEX(CHAR(0), UserID) = 0);
EDIT
Ok, so that is definitely a 4-digit integer followed by six instances of CHAR(0). And the workaround I posted definitely works for me:
DECLARE #foo TABLE(UserID VARCHAR(32));
INSERT #foo SELECT 0x31353831000000000000;
-- this succeeds:
SELECT CONVERT(INT, REPLACE(UserID, CHAR(0), '')) FROM #foo;
-- this fails:
SELECT CONVERT(INT, UserID) FROM #foo;
Please confirm that this code on its own (well, the first SELECT, anyway) works for you. If it does then the error you are getting is from a different non-numeric character in a different row (and if it doesn't then perhaps you have a build where a particular bug hasn't been fixed). To try and narrow it down you can take random values from the following query and then loop through the characters:
SELECT UserID, CONVERT(VARBINARY(32), UserID)
FROM dbo.[audit]
WHERE UserID LIKE '%[^0-9]%';
So take a random row, and then paste the output into a query like this:
DECLARE #x VARCHAR(32), #i INT;
SET #x = CONVERT(VARCHAR(32), 0x...); -- paste the value here
SET #i = 1;
WHILE #i <= LEN(#x)
BEGIN
PRINT RTRIM(#i) + ' = ' + RTRIM(ASCII(SUBSTRING(#x, #i, 1)))
SET #i = #i + 1;
END
This may take some trial and error before you encounter a row that fails for some other reason than CHAR(0) - since you can't really filter out the rows that contain CHAR(0) because they could contain CHAR(0) and CHAR(something else). For all we know you have values in the table like:
SELECT '15' + CHAR(9) + '23' + CHAR(0);
...which also can't be converted to an integer, whether you've replaced CHAR(0) or not.
I know you don't want to hear it, but I am really glad this is painful for people, because now they have more war stories to push back when people make very poor decisions about data types.
This question has got 91,000 views so perhaps many people are looking for a more generic solution to the issue in the title "error converting varchar to INT"
If you are on SQL Server 2012+ one way of handling this invalid data is to use TRY_CAST
SELECT TRY_CAST (userID AS INT)
FROM audit
On previous versions you could use
SELECT CASE
WHEN ISNUMERIC(RTRIM(userID) + '.0e0') = 1
AND LEN(userID) <= 11
THEN CAST(userID AS INT)
END
FROM audit
Both return NULL if the value cannot be cast.
In the specific case that you have in your question with known bad values I would use the following however.
CAST(REPLACE(userID COLLATE Latin1_General_Bin, CHAR(0),'') AS INT)
Trying to replace the null character is often problematic except if using a binary collation.
This is more for someone Searching for a result, than the original post-er. This worked for me...
declare #value varchar(max) = 'sad';
select sum(cast(iif(isnumeric(#value) = 1, #value, 0) as bigint));
returns 0
declare #value varchar(max) = '3';
select sum(cast(iif(isnumeric(#value) = 1, #value, 0) as bigint));
returns 3
I would try triming the number to see what you get:
select len(rtrim(ltrim(userid))) from audit
if that return the correct value then just do:
select convert(int, rtrim(ltrim(userid))) from audit
if that doesn't return the correct value then I would do a replace to remove the empty space:
select convert(int, replace(userid, char(0), '')) from audit
This is how I solved the problem in my case:
First of all I made sure the column I need to convert to integer doesn't contain any spaces:
update data set col1 = TRIM(col1)
I also checked whether the column only contains numeric digits.
You can check it by:
select * from data where col1 like '%[^0-9]%' order by col1
If any nonnumeric values are present, you can save them to another table and remove them from the table you are working on.
select * into nonnumeric_data from data where col1 like '%[^0-9]%'
delete from data where col1 like '%[^0-9]%'
Problems with my data were the cases above. So after fixing them, I created a bigint variable and set the values of the varchar column to the integer column I created.
alter table data add int_col1 bigint
update data set int_col1 = CAST(col1 AS VARCHAR)
This worked for me, hope you find it useful as well.