I have a string column that represents hex values, for example -
'274', '1A7', '3D1' and so on.
Now I need to convert these values to their integer values, so that '10' will be converted to 16, for example.
The code I use:
SELECT CONVERT(int, CONVERT(varbinary, '0x' + case when replicate('0', len(myHex) / 2) + myHex = '0' then '00' else replicate('0', len(myHex) / 2) + myHex end, 1))
I'm actually padding the string with a zero or two to make it's length even, and adding the '0x' prefix. However some (random) rows fail.
Is there another way to convert the values?
Thanks.
please give feedback
so that i can improve my answer
Here is one way to do it:
//create function fn_HexToIntnt(#str varchar(16))
//returns bigint as begin
select #str=upper(#str)
declare #i int, #len int, #char char(1), #output bigint
select #len=len(#str)
,#i=#len
,#output=case
when #len>0
then 0
end
while (#i>0)
begin
select #char=substring(#str,#i,1), #output=#output
+(ASCII(#char)
-(case
when #char between ‘A’ and ‘F’
then 55
else
case
when #char between ’0′ and ’9′
then 48 end
end))
*power(16.,#len-#i)
,#i=#i-1
end
return #output
end
or
SELECT CONVERT(INT, 0×00000100)
SELECT CONVERT(VARBINARY(8), 256)
Related
I have a varbinary column and a bit number which can be bigger than 32. How can I set/test a bit having it's number in the varbinary column?
I tried to do
convert(varbinary(max), power(2, #bit_number))
to get me varbinary, but it is limited to float size numbers.
There is an extended stored procedure which can do OR of two varbinaries in our DB but I need to pass this long varbinary mask, or maybe there is a way to update some byte in varbinary knowing it's number?
You can always convert the varbinary to a string, manipulate it, and convert it back. For example, try this:
DECLARE #Foo varbinary(max)
SELECT #Foo = 0x0123456789abcdef0123456789abcdef
DECLARE #Temp varchar(max)
SELECT #Temp = CONVERT(varchar(max), #Foo, 1)
DECLARE #ByteOffset integer;
SELECT #ByteOffset = 3 --offset into varbinary to access
DECLARE #GetValue binary(1)
SELECT #GetValue = CONVERT(binary(1), '0x' + SUBSTRING(#Temp, (#ByteOffset * 2) + 3, 2),1 )
PRINT #GetValue -- fetch the value at #ByteOffset
DECLARE #SetValue binary(1)
SELECT #SetValue = 0x04 --value to modify
DECLARE #Foo2 varbinary(max)
SELECT #Foo2 = CONVERT(varbinary(max), SUBSTRING(#Temp, 1, (#ByteOffset * 2) + 2) + SUBSTRING(CONVERT(varchar, #SetValue, 1), 3, 2) + SUBSTRING(#Temp, (#ByteOffset * 2) + 5, LEN(#Temp)), 1)
PRINT #Foo2 --contains the new varbinary with #ByteOffset updated with #SetValue
Below is some test SQL. IsNumeric is saying the substring of 05031, is numeric, but fails when it tries to convert it to an actual number because of the ,. Is this a bug in SQL?
DECLARE #Str NVARCHAR(20)
SET #Str = 'XYZ 505031, some text'
SELECT CASE WHEN ISNUMERIC(SUBSTRING(#Str,6,7)) = 1 THEN CONVERT(int,SUBSTRING(#Str,6,7)) ELSE 0 END, SUBSTRING(#Str,6,7)
you should use try_cast instead, because ISNUMERIC evaluates to 1 for 5031,
ISNUMERIC returns 1 for some characters that are not numbers, such as plus (+), minus (-), and valid currency symbols such as the dollar sign ($). For a complete list of currency symbols, see money and smallmoney (Transact-SQL).
DECLARE #Str NVARCHAR(20)
SET #Str = 'XYZ 505031, some text'
SELECT
CASE
WHEN TRY_CAST(SUBSTRING(#Str,6,7) AS DECIMAL(10,2)) IS NOT NULL
THEN CONVERT(int,SUBSTRING(#Str,6,7))
ELSE 0
END,
SUBSTRING(#Str,6,7)
If 2012+, you can use Try_Convert(). We use MONEY becase the this will convert the leading zero, and then we convert to int
Example
DECLARE #Str NVARCHAR(20)
SET #Str = 'XYZ 505031, some text'
SELECT AsInt = IsNull(try_convert(int,try_convert(money,SUBSTRING(#Str,6,7))),0)
, AsStr = SUBSTRING(#Str,6,7)
Returns
AsInt AsStr
5031 05031,
This is because your substring is also pulling a comma in the end.
SELECT SUBSTRING(#Str, 6, 7);
is resulting:
05031,
Whereas,
SELECT SUBSTRING(#Str, 6, 5);
is resulting:
05031
And
SELECT CASE WHEN ISNUMERIC(SUBSTRING(#Str,6,5)) = 1 THEN CONVERT(int,SUBSTRING(#Str,6,5)) ELSE 0 END, SUBSTRING(#Str,6,5)
is resulting:
5031 | 05031
How to convert string '۱۳۹۴' to '1394'?
I try change collation but does not work.
Please note that I read data from external device in C# .
i have tried to solve problem after search on internet i came to the conclusion the best way to solve this problem is function
ALTER FUNCTION [dbo].[udf_ReplaceArabicNumbers]
(#str NVARCHAR(1000))
RETURNS NVARCHAR(2000)
AS
BEGIN
DECLARE #i INT = 1
WHILE #i<=LEN(#str)
BEGIN
DECLARE #val NVARCHAR(1)
SET #val = SUBSTRING(#str, #i, 1)
DECLARE #newchar NVARCHAR(1)
SET #newchar = CASE(#val)
WHEN N'۱' THEN 1
WHEN N'۲' THEN 2
WHEN N'۳' THEN 3
WHEN N'۴' THEN 4
WHEN N'۵' THEN 5
WHEN N'۶' THEN 6
WHEN N'۷' THEN 7
WHEN N'۸' THEN 8
WHEN N'۹' THEN 9
WHEN N'۰' THEN 0
END
SET #str = REPLACE(#str, #val, #newchar)
SET #i+=1;
END
RETURN #str
END
and call to this function
select [dbo].[udf_ReplaceArabicNumbers] (N'۱۳۹۴')
i refer this site http://unicode-table.com/en/
with the help of UNICODE we can get HTML-Code and use in our Program
select '&#' + cast (UNICODE(N'۱')as nvarchar(10)) + ';',
'&#' + cast (UNICODE(N'۳')as nvarchar(10)) + ';',
'&#' + cast (UNICODE(N'۹')as nvarchar(10)) + ';',
'&#' + cast (UNICODE(N'۴')as nvarchar(10)) + ';'
and result would be
Based on the properties of the unicode code points numbers, you could use something like this:
DECLARE #ArabicNumber NVARCHAR(4)
SET #ArabicNumber=N'۱۳۹۴'
SELECT
LEFT(CONVERT(NVARCHAR(4),CONVERT(VARBINARY(8),
CONVERT(BIGINT,CONVERT(VARBINARY(8),CONVERT(NCHAR(4),#ArabicNumber)))
& CONVERT(VARBINARY(8),REPLICATE(0x0F00,4))
^ CONVERT(VARBINARY(8),REPLICATE(0x3000,4))
)),LEN(#ArabicNumber))
This works if the input string contains only numbers and it is limited to 4 characters, to fit in a bigint, for the bitwise operations. For longer strings, you should use a WHILE loop to process each character.
I have a monetary value like 1.223.01 but it is stored as a varchar so it is really like '1.223.01'.
I need this to be converted to decimal so I can do some calculations on it.
What I have tried is
SELECT Convert(decimal(18,2), '1.223.01') AS test
But I get a conversion error.
How can I convert this?
You've not specified what the output should be, so it's either 1223.01 or 122301.00 that you require.
So using some basic string manipulation you can get both of those values:
DECLARE #val AS VARCHAR(20) = '1.223.01'
-- remove all decimal points
SET #val = REPLACE(#val, '.', '')
-- convert value without decimals to get 122301.00
SELECT CONVERT(decimal(18,2), #val) AS TestValue
-- add a decimal point before the last 2 digits to get 1223.01
SELECT CONVERT(decimal(18,2), LEFT(#val,LEN(#val) - 2) + '.' +
RIGHT(#val, 2)) AS TestValue
This assumes that the values stored always have a decimal point with 2 digits after it.
Both can be done in a single SELECT if required, by substituting REPLACE(#val, '.', '') into the position of #val in the 2 queries.
DECLARE #val AS VARCHAR(20) = '1.223.01'
SELECT CONVERT(DECIMAL(18, 2), REPLACE(#val, '.', '')) AS TestValue
SELECT CONVERT(DECIMAL(18, 2), LEFT(REPLACE(#val, '.', ''),
LEN(REPLACE(#val, '.', '')) - 2) + '.'
+ RIGHT(REPLACE(#val, '.', ''), 2)) AS TestValue
I never heard of that format. Sounds like you have a varchar and not a money type. Here is how you can manipulate it.
First removing all periods. Then dividing by 1 to explain to sql-server that this is a numeric. Then multiply by .01 to change it into a decimal number
SELECT
replace(value, '.', '')/1*.01
FROM (values('1.223.01'),('1.111.223.75'),('0.01')) x(value)
Result:
1223.01
1111223.75
0.01
Does anyone have in their back pocket a function that can achieve this?
Found this here :-
create function ProperCase(#Text as varchar(8000))
returns varchar(8000)
as
begin
declare #Reset bit;
declare #Ret varchar(8000);
declare #i int;
declare #c char(1);
select #Reset = 1, #i=1, #Ret = '';
while (#i <= len(#Text))
select #c= substring(#Text,#i,1),
#Ret = #Ret + case when #Reset=1 then UPPER(#c) else LOWER(#c) end,
#Reset = case when #c like '[a-zA-Z]' then 0 else 1 end,
#i = #i +1
return #Ret
end
Results from this:-
select dbo.propercase('ALL UPPERCASE'); -- All Uppercase
select dbo.propercase('MiXeD CaSe'); -- Mixed Case
select dbo.propercase('lower case'); -- Lower Case
select dbo.propercase('names with apostrophe - mr o''reilly '); -- Names With Apostrophe - Mr O'Reilly
select dbo.propercase('names with hyphen - mary two-barrels '); -- Names With Hyphen - Mary Two-Barrels
I'd do this outside of TSQL, in the calling code tbh.
e.g. if you're using .NET, it's just a case of using TextInfo.ToTitleCase.
That way, you leave your formatting code outside of TSQL (standard "let the caller decide how to use/format the data" approach).
This kind of function is better done on the application side, as it will perform relatively poorly in SQL.
With SQL-Server 2005 and above you could write a CLR function that does that and call it from your SQL. Here is an article on how to do this.
If you really want to do this in T-SQL and without a loop, see Tony Rogerson's article "Turning stuff into "Camel Case" without loops"
I haven't tried it... that's what client code it for :-)
No cursors, no while loops, no (inline) sub-queries
-- ===== IF YOU DON'T HAVE A NUMBERS TABLE =================
--CREATE TABLE Numbers (
-- Num INT NOT NULL PRIMARY KEY CLUSTERED WITH(FILLFACTOR = 100)
--)
--INSERT INTO Numbers
--SELECT TOP(11000)
-- ROW_NUMBER() OVER (ORDER BY (SELECT 1))
--FROM master.sys.all_columns a
-- CROSS JOIN master.sys.all_columns b
DECLARE #text VARCHAR(8000) = 'my text to make title-case';
DECLARE #result VARCHAR(8000);
SET #result = UPPER(LEFT(#text, 1));
SELECT
#result +=
CASE
WHEN SUBSTRING(#text, Num - 1, 1) IN (' ', '-') THEN UPPER(SUBSTRING(#text, Num, 1))
ELSE SUBSTRING(#text, Num, 1)
END
FROM Numbers
WHERE Num > 1 AND Num <= LEN(#text);
PRINT #result;
Will any given row only contain a firstname or a lastname that you wish to convert or will it contain full names separated by spaces? Also, are there any other rules you wish to what characters it should "upper" or lower"?
If you can guarantee that it's only first and last names and you aren't dealing with any specialized capitalization such as after an apostrophe, might this do what you're looking for?
SELECT -- Initial of First Name
UPPER(LEFT(FullName, 1))
-- Rest of First Name
+ SUBSTRING(LOWER(FullName), 2, CHARINDEX(' ', FullName, 0) - 2)
-- Space between names
+ ' '
-- Inital of last name
+ UPPER(SUBSTRING(FullName, CHARINDEX(' ', FullName, 0) + 1, 1))
-- Rest of last name
+ SUBSTRING(LOWER(FullName), CHARINDEX(' ', FullName, 0) + 2, LEN(FullName) - CHARINDEX(' ', FullName, 0) + 2)
FROM Employee