How to convert from nchar to decimal in SQL? - sql

I have 2 tables(source and destination) which are respectively NOR_LABOR and ALL_LABOR_DETAILS. In the source table(NOR_LABOR) there is a column "feet_produced" with the data type "nchar(10)". In the destination table(ALL_LABOR_DETAILS) there's a column "labor_feet_produced" with the data type "decimal(18,4)". I want to convert the "feet_produced" from nchar(10) to decimal(18,4) and paste it in the "ALL_LABOR_DETAILS" table's "labor_feet_produced" column.
I have found a code regarding a simillar issue but did not do the exact as I need to do, following is that code snippet :
Select feet_produced AS feet_produced_s, CASE WHEN Isnumeric(feet_produced) = 1
THEN CONVERT(DECIMAL(18,2),feet_produced)
ELSE 0 END AS feet_produced
INTO [MES_DEV].[dbo].[ALL_LABOR_DETAILS]
from [dbo].[NOR_LABOR]
Thank you!

There are values that will test true for IS_NUMERIC, but will fail to convert to decimal.
Instead, use TRY_CONVERT which will return either the successfully-converted-to-decimal value, or a NULL when it fails. (You can then COALESCE to zero to get your desired result).
Here is a short example set of values, using TRY_CONVERT:
SELECT
TryConvert = COALESCE(TRY_CONVERT(decimal(18,4),TestValues),0)
FROM (
VALUES('10.6'),
('ten'),
('7d2'),
('10000000000'),
('10.00000001')
) AS x(TestValues);
The same set of values using your example code will throw an error:
SELECT
IsNumericCase = CASE
WHEN Isnumeric(TestValues) = 1
THEN CONVERT(DECIMAL(18,2),TestValues)
ELSE 0
END
FROM (
VALUES('10.6'),
('ten'),
('7d2'),
('10000000000'),
('10.00000001')
) AS x(TestValues);
This error is returned because 7d2 is numeric, but cannot be converted to decimal.
Msg 8114, Level 16, State 5, Line 14
Error converting data type varchar to numeric.

Im not sure what the issue is with the code that dose not work for you.
But here is how I would do it with a small change in the statement that you just post it.
insert into[MES_DEV].[dbo].[ALL_LABOR_DETAILS](labor_feet_produced)
select CONVERT(DECIMAL(18, 4), feet_produced) AS feet_produced_s from[dbo].[NOR_LABOR]

Related

Error converting varchar value to data type int

I am trying to concatenate two integer values with hyphen in between. So when I try to do the same, SQL gives me the error.
Conversion failed when converting the varchar value '30-45' to data type int.
NOTE:
Also, the second value for concatenation can be null so in that case, a hyphen should not be concatenated.
example
from1 = 30
to1 = 45
case
to1 is null
then from1
else CONCAT(from1, '-' + nullif(to1,'')) end
AS age
//This works but shows 3045 instead of 30-45.
concat(from, '-', to) AS age
//This doesn't work out as it gives the error 'Conversion failed when converting the varchar value '30-45' to data type int.'
Thanks for the help in advance and looking forward to it.
DECLARE #FROM INT=30;
DECLARE #TO INT=45;
SELECT CAST(#FROM AS VARCHAR(2))+'-'+CAST(ISNULL(#TO,'') AS VARCHAR(2));
SQL is trying to convert your phrase to int probably because it's part of CASE statement. It uses the first route to determine the output type.
In your case- you put NULL as the first route option in your CASE, so it is determined as int. try putting instead of it this: CAST(NULL AS VARCHAR(10))
It seems that for some reason you think that strings that contain mathematical expressions are resolved as said expression, not an as literal string. Thus if you have the varchar value '30-45' you think it'll return the int value -15; this isn't true. This in fact isn't true in any language, let alone T-SQL.
For what you have, in your ELSE the '-' isn't a minus... It's a string... - is a minus. If you want to substract a number from another then it's a basic maths expression: a - b. You're effectively doing CONVERT(varchar,a) + '-' + CONVERT(varchar,b)... Just have your ELSE as the following:
from1 - NULLIF(to1,0)
This will return NULL if from1 has the value NULL, or to1 has the value NULL or 0.
Please check below code. It's working
example
#from1 = 30
#to1 = 45
IF #to1 is null
SELECT #from1
ELSE
SELECT CONCAT(#from1, '-' , nullif(#to1,'')) as age

Update Accumulated Value with CTE error because of decimal datatype (SQL)

I am trying to get the accumulated value of the column MontanteRecuperacao into montanterecuperacao_acumulada, by date and contract.
But the decimal datatype is becoming a problem and I don't know why, this works when the variables are of INT type.
This is the error message
Msg 4187, Level 16, State 1, Procedure spCalculaRecuperacao, Line 123
Data type decimal of receiving variable cannot store all values of the data type decimal of column 'montanterecuperacao_acumulada' without data loss.
Code:
DECLARE #MontanteRecuperacao_running DECIMAL,
#montanterecuperacao_acumulada_running DECIMAL,
#Contrato VARCHAR(10) = '' ;
WITH CTE AS
(
SELECT TOP 100 PERCENT
MontanteRecuperacao, montanterecuperacao_acumulada, ContratoId
FROM
MovimentoRecuperacao
ORDER BY
[ContratoId], [DtReferencia] DESC
)
UPDATE CTE
SET #montanterecuperacao_acumulada_running = montanterecuperacao_acumulada =
CASE
WHEN #Contrato <> ContratoId
THEN montanterecuperacao_acumulada
ELSE #montanterecuperacao_acumulada_running - #MontanteRecuperacao_running
END,
#MontanteRecuperacao_running = MontanteRecuperacao,
#Contrato = ContratoId
You've declared your DECIMAL parameters without specifying precision or scale:
#MontanteRecuperacao_running DECIMAL , #montanterecuperacao_acumulada_running DECIMAL
The default values are DECIMAL(18,0), which is essentially an integer. In order to get the behavior you desire, you'll need to assess your data for proper values to assign.

How to convert varchar(4) to float in SQL Server 2008?

I'm trying to convert my database fields from VARCHAR(4) to FLOAT. Some of the values in these fields might not be digits since these fields didn't have any validation prior. My main target is to convert any integer or decimal value in float format and save in new database field. For this process I use INSERT SELECT STATEMENT from old table into the new table. So far I have this line of code for my conversion:
CASE WHEN LEN(LTRIM(RTRIM(hs_td2))) <> 0 AND ISNUMERIC(hs_td2) = 1 THEN CAST(LTRIM(RTRIM(hs_td2)) AS float) ELSE NULL END AS hs_td2
First step I trim the value then check if it's numeric and then convert to float otherwise set to NULL. With the code above I'm getting this error message in Microsoft Studio:
Msg 8114, Level 16, State 5, Line 13
Error converting data type varchar to float.
Line 13th is beginning of my SELECT statement. Then I tried this conversion as well:
CASE WHEN LEN(LTRIM(RTRIM(hs_td2))) <> 0 AND ISNUMERIC(hs_td2) = 1 THEN CONVERT(FLOAT, LTRIM(RTRIM(hs_td2))) ELSE NULL END AS hs_td2
and I got the same error message. Values in my fields could be something like this:
10 or 5 or -10 or 0.9 or 11.6 or -11.89 and so on...
I'm wondering if isNumeric() is the best function that I should use and why my code produces the error message listed above?
If anyone can help please let me know. Thank you!
No, ISNUMERIC is not the best function to use.
Essentially, this question has been asked before, though not in this wording:
Try_Convert for SQL Server 2008 R2
The most upvoted answer recommends to cast to XML to use XML-specific casting function:
DECLARE #T TABLE (v varchar(4));
INSERT INTO #T (v) VALUES
('1g23'),
('-1.8'),
('11.6'),
('akjh'),
('.'),
('-'),
('$'),
('12,5');
select
cast('' as xml).value('sql:column("V") cast as xs:float ?', 'float') as new_v
from #T
I'll leave my first version of the answer below.
Most likely you are getting the conversion error because the server tries to run CAST(LTRIM(RTRIM(hs_td2)) AS float) for each row of the table, not only for those that are numeric.
This usually happens when you try to filter out non-numeric rows using the WHERE ISNUMERIC(...) = 1 filter. Technically it may happen in CASE expression as well.
That's why they added TRY_CONVERT in 2012.
I'd try to write my own user-defined function that uses TRY-CATCH and tries to convert the given value. Yes, it will be slow.
Having said that, the example below with CASE runs fine:
DECLARE #T TABLE (v varchar(4));
INSERT INTO #T (v) VALUES
('123'),
('-1.8'),
('11.6'),
('akjh'),
('123');
SELECT
CASE WHEN ISNUMERIC(v) = 1 THEN CAST(v AS float) ELSE NULL END AS new_v
FROM #T;
Result
+-------+
| new_v |
+-------+
| 123 |
| -1.8 |
| 11.6 |
| NULL |
| 123 |
+-------+
But, if I put a . or - or $ value, like so:
INSERT INTO #T (v) VALUES
('123'),
('-1.8'),
('11.6'),
('akjh'),
('$');
The query fails:
Error converting data type varchar to float.
There may be other special characters and their combinations that ISNUMERIC would not complain about. That's why I originally said that overall, ISNUMERIC is not the best function to use.
If it is a one-off conversion, you can try to build a LIKE expression to catch all special cases that are present in your data, but if you need a reliable generic solution, upgrade to 2012+ and use TRY_CONVERT or write your T-SQL UDF, or your CLR UDF.
Sqlxml has enough power to make magic. Of course, the performance is the problem. But still better, than million of conditions
DECLARE #T TABLE (v varchar(4));
INSERT INTO #T (v) VALUES
('123'),('-1.8'),('11.6'),('akjh'),('$'),('-.'),('-.1'),(NULL);
declare #Xml xml = (SELECT v FROM #T T for xml auto,elements);
select T.v.value('v[1]','varchar(4)') v, T.v.value('max(v[1])','float') converted_v
from #xml.nodes('/T') T(v);
It depends on the values in your varchar columns
ISNUMBER() for vaule such as '.' and '-' will return 1, however, it will failed when you CAST to FLOAT
ISNUMBER() for value such as '3D2' , '1e2' will return 1, and can be CAST to FLOAT, however, you may not want consider it as number.
You may try the following to convert
CASE WHEN
not LTRIM(RTRIM(hs_td2))like '%[^0-9.,-]%' -- Value only contains 0-9 . -
and LTRIM(RTRIM(hs_td2)) not like '.' -- can not be only .
and LTRIM(RTRIM(hs_td2)) not like '-' -- can not be only -
and isnumeric(LTRIM(RTRIM(hs_td2))) = 1
THEN CAST(LTRIM(RTRIM(hs_td2)) AS float)
ELSE NULL
END

Why am I unable to convert datatype to return blank cells for values of 0 or NULL?

I am currently trying to return '' for values that are either NULL or 0, but am unable to do so:
select isnull(cast(sec_column as varchar(10)),'')
sec_column is Numeric
The above produces the follow sql error:
"Arithmetic overflow error converting numeric to data type varchar"
Additionally, I have tried something simpler along the lines of an ISNULL to achieve this, but to no avail:
select isnull(sec_column,'')
I assume that I should be able to cast as a string value and return blank. Any insight into this would be much appreciated!
That error for the given code would indicate you need a larger varchar():
select isnull(cast(sec_column as varchar(39)),'')
declare #val numeric(38,2) = '123456789123456789123456789123456789.12'
/* works fine */
select convert(varchar(39),#val)
select convert(varchar(10),#val)
/* Arithmetic overflow error converting numeric to data type varchar. */
rextester demo: http://rextester.com/GMYUUN51608
Perhaps this can help.
Assuming sec_column is a numeric, and you want to show zeros and nulls as ""
select isnull(cast(nullif(sec_column,0) as varchar(10)),'')
Example
Declare #YourTable Table (sec_column int)
Insert Into #YourTable Values
(1)
,(null)
,(25)
,(0)
select *
,AsString = isnull(cast(nullif(sec_column,0) as varchar(10)),'')
From #YourTable
Returns
sec_column AsString
1 1
NULL
25 25
0

select case statement error in mssql

SELECT top 1
case
when VR = -99999.99
then 0
else cast((VR*1.732) as decimal(38,3))
end
FROM pseb.dbo.datasource
where FeederID=5003
order by datetime desc
The above query is working fine, but I need to return varchar value '--' instead of returning 0
if I do like that
SELECT top 1
case
when VR = -99999.99
then '--'
else cast((VR*1.732) as decimal(38,3))
end
FROM pseb.dbo.datasource
where FeederID=5003
order by datetime desc
means it returns the following error:
Msg 8114, Level 16, State 5, Line 1 Error converting data type varchar
to numeric.
please help me to solve it
The problem is that you are returning two different data types from the same column. The rule with SQL Server that numeric types take precedence over string types, i.e. in a situation like yours a string gets converted to a number, not the other way around.
So to solve this you can cast your number to a string.
One option is to do something like this:
SELECT top 1
case when VR = -99999.99 then '--'
else
cast
(
cast((VR*1.732) as decimal(38,3)
)
as varchar(50))
end
FROM pseb.dbo.datasource where FeederID=5003 order by datetime desc