I have value like this
DECLARE #hex VARCHAR(64) = '00E0'
and I need to convert this value to a double.
I have code in C language
double conver_str_to_temp(char *strTemp)
{
int iTemp;
double fTemp;
iTemp = strtoul(strTemp, 0, 16); //strTemp is the string get from the message.
if (iTemp & 0x8000) //This means this is a negative value
{
iTemp -= 0x10000;
}
fTemp = iTemp * 0.0625;
return fTemp;
}
Result for :'00E0' is 14.000000
Result for : 'FF6B' is -9.312500
But problem is I'm not good in T-SQL.
How can I convert this C code to T-SQL function for use in SQL Server ?
There's no function to convert a string containing a hexadecimal value to a number directly. But you can use intermediate conversion to varbinary, which could then be easily converted to an integer.
However, when converting to a varbinary, you will need to specify the correct format, so that the string is interpreted as a hexadecimal value (rather than a string of arbitrary digits and letters). This
CONVERT(varbinary, '00E0')
which in fact defaults to CONVERT(varbinary, '00E0', 0), will result in every character being converted individually, because that's what the 0 format specifier does. So, every '0' will be converted to 0x30 and 'E' to 0x45, which will ultimately give you 0x30304530 – most probably not the result you want.
In contrast, this
CONVERT(varbinary, '00E0', 2)
results in 0x00E0, because the 2 format specifier tells the function to interpret the string as a (non-prefixed) hexadecimal value.
Now that you've got the correct varbinary representation of the string, you can use either of the methods suggested by #armen to convert the value to an integer: like this
CONVERT(varbinary, '00E0', 2) * 1
or like this:
CONVERT(int, CONVERT(varbinary, '00E0', 2))
To explain the former method a little, it uses implicit conversion: since the other operand of multiplication, 1, is an int and int has higher precedence than varbinary, the varbinary operand is implicitly converted to int (which gives 224 in this particular case) before the multiplication can take place.
You can read more about conversion in the manual.
try this-:
DECLARE #hex VARCHAR(64) = '00E0'
SELECT CONVERT(VARBINARY, #hex) * 1
-- OR
SELECT CONVERT(INT, CONVERT(VARBINARY, #hex))
in TSQL, you need not employ a conversion function,
SQL Server will convert the HEX value into the integer intrinsically.
in your case you can do the below
declare #hex float
set #hex = 00E0
select #hex
Related
I have an object with an number of type float, and I was curious why the following SQL statement does not work, but the one below it does.
SELECT TOP (1000) [number]
FROM [object]
WHERE CONVERT(varchar(255), number) LIKE '%201608147%'
Results in "0 rows found".
SELECT TOP (1000) [number]
FROM [object]
WHERE CONVERT(varchar(255), CONVERT(decimal(20, 2), number)) LIKE '%201608147%'
Results in 1 row found
Edit: I was asked to execute the following:
SELECT
number,
CONVERT(varchar(255), number),
CONVERT(varchar(255), CONVERT(decimal(20, 2), number))
FROM [object]
This yielded the following result:
number : 201608147
number cast to string: 201608147
number cast to decimal: 201608147.00
To show it is really a float:
After simulation I found the following:
select nbr, Convert(varchar(255), nbr), Convert(varchar(255), Convert(decimal(20,2), nbr)) from tbl_XYZ
201608147 2.01608e+008 201608147.00
The Convert(varchar(255), nbr) returns the scientific notation of the number at hand as a string value; consequently the value does not match your pattern :
LIKE '%201608147%'
The reason behind this behavior is that the Float DataType is used to hold the binary (base-2) approximation of a number and not a precise decimal value.
Floating point numbers are often shown in scientific notation. These types are used when range is more important than absolute precision.
The numbers quickly become unwieldy in other formats. Scientific notation also helps to emphasise the limited precision.
You can see the different ways that different functions can be used to format floating-point numbers in this example.
DECLARE #float float = 201608147;
SELECT TheNumber = #float;
SELECT ConvertWithoutStyle = CONVERT(varchar(255),#float),
ConvertWithStyle0 = CONVERT(varchar(255),#float,0),
ConvertWithStyle1 = CONVERT(varchar(255),#float,1),
ConvertWithStyle2 = CONVERT(varchar(255),#float,2),
ConvertWithStyle3 = CONVERT(varchar(255),#float,3);
For a float, style can have one of the values shown below. Other values are processed as 0.
Value Output
0 (default) A maximum of 6 digits. Use in scientific notation, when appropriate.
1 Always 8 digits. Always use in scientific notation.
2 Always 16 digits. Always use in scientific notation.
3 Always 17 digits. Use for lossless conversion. With this style, every distinct float or real value is guaranteed to convert to a distinct character string.
You are using an implicit conversion from float to varchar(255), which implicitly uses style 0. Your float has more than six digits, so it is represented in scientific notation.
You might like to use STR or FORMAT instead.
I'd like to convert char with leading zeros to int, ex '00010' to 00010. I've tried to use CAST or CONVERT :
select CONVERT(int, '00010')
but the function removes zeros at the beginning and return 10 instead of 00010.
Do you know any easy solution to this? The length of input will be allways 5.
Mathematically, leading zeros are meaningless, so an Int can't have leading zeros.
If you need to display leading zeroes, you can always convert to varchar and use concatenation with right, like this:
DECLARE #MyVal int = 10;
SELECT RIGHT('00000' + CAST(#MyVal as varchar(5)), 5)
You must read about data types. An INT is noting more than a bit pattern. Whenever you see the number in a human readable format, the actual value is translated to a string consisting of digits. But this digit format is not the actual INT.
Leading Zeros are never part of the INT itself, but may be added to the string representation. So your question (taken literally) does not make any sense actually.
If there is a string like 00012 and you want to use it like a number, you should just cast it:
SELECT CAST('00012' AS INT) + 2; --14
Other answers show you some approaches to get a padded string representation out of an INT, but this is the opposite direction:
SELECT REPLACE((STR(12,5),' ','0'); --00012
You can combine these approaches:
DECLARE #PaddedNumber CHAR(5)='00012'
SELECT REPLACE(STR(CAST(#PaddedNumber AS INT) + 2,5),' ','0'); --00014
The padded number (which is - by type! - a string) is casted to an INT, then used in computation. The result is an INT, which can be converted to a padded string. But the final result's type is string...
SELECT FORMAT(CONVERT(INT,'00010'), 'd5')
should solve the problem :)
Declare #Precision INTEGER
Set #precision = 3
-> I have a select statement here which selects the integer value
and if their is a way that I can use this #precision in numeric data type for example something like this
numeric(20,#precision)
You want to use the str() function (documented here).
It allows you to convert numerics to strings, while controlling the precision.
For instance:
select str(3.14158165, 5, 3)
Returns '3.142'.
There are great posts on how to use JAVA to create a MYSQL MD5 hash, however is it possible to go the other way - use SQL to produce what java does ?
in SQL:
Select MD5('secret') = 5ebe2294ecd0e0f08eab7690d2a6ee69
in Java, the MD5 algo yields: 94-6634-108-20-48-32-16-114-85118-112-46-90-18105
First off I can see the Java one is a decimal representation, so pairing off the SQL output and converting to DECIMAL gives: 9419034148236208224240142171118144210166238105
The only part that's the same is the Front 2 and last 4.
Anyone have ideas on how to use SQL to generate what Java would produce?
I don't have this fully worked out, but hopefully, these hints will help:
In Java, if you take the direct result of the md.digest() call, you have a byte array.
Instead of converting that to a String representation, just output the bytes as Integers.
You'll see that they are:
94
-66
34
-108
-20
-48
-32
-16
-114
-85
118
-112
-46
-90
-18
105
So, the dashes in the resulting string conversion aren't separators, they are arithmetic signs.
The java hash is a simple concatenation of the byte values as (signed) ints.
When you Select MD5('secret'), you getting a string of 32 hex digits.
I verified that if in Java, you convert each byte to it's hex representation, and concatenate them, you get the same string that MySQL returns.
So, it seems to me that what you would need to do in MySQL is to iterate the result of Hex(), one hex char at a time (perhaps using SUBSTRING()), convert each to decimal, and concatenate them.
Edit - looks like you are almost doing it correctly, but you need to convert each pair of hex digits to Byte instead of int, so for example, '0xbe' is -66, not 190
Edit #2 - I was intrigued by how relatively difficult this is to do in MySQL, so I persisted (joke intended). The following stored function seems to do the job:
drop function if exists java_md5;
delimiter |
create function java_md5(secret VARCHAR(255))
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
DECLARE result varchar(255);
DECLARE md5String char(255);
DECLARE pair char(2);
DECLARE pairInt int;
DECLARE idx int;
set md5String = MD5(secret);
set result = '';
set idx = 1;
WHILE(idx < 32) DO
set pair = substring(md5String, idx, 2);
set pairInt = ascii(unhex(pair));
set pairInt = if(pairInt > 127, pairInt - 256, pairInt);
set result = concat(result, pairInt);
set idx = idx + 2;
END WHILE;
RETURN result;
END|
delimiter ;
select java_md5('secret');
PRINT CONVERT(NUMERIC(18,0), '')
produces Error converting data type varchar to numeric.
However,
PRINT CONVERT(INT, '')
produces 0 without error...
Question: Is there some SQL Server flag for this or will I need to do case statements for every varchar to numeric conversion? (aside from the obvious why?)
Use ISNUMERIC
declare #a varchar(20)
set #a = 'notanumber'
select case when isnumeric(#a) = 0 then 0 else convert(numeric(18,0),#a) end
ISNUMERIC doesn't alway work as you might expect: in particular it returns True for some values that can't subsequently be converted to numeric.
This article describes the issue and suggests how to work around it with UDFs.
Empty string will convert to zero for float and int types, but not decimal. (And converts to 01 Jan 1900 for datetimes = zero). I don't know why.. it just is...
If you need decimal(18,0), use bigint instead. Or cast via float first
ISNUMERIC will accept - and . and 1.2E3 as a number, but all fail to convert to decimal.