Convert from bigint to varchar without leading 0? - sql

I need to use a bigint value as part of a string construction, but I can't figure out how to get from bigint to to varchar without having a leading 0
declare #a bigint = 167830720612159876
select convert(varchar(32), convert(varbinary, #a), 2)
This gives me 02544126B47C5184, but I want `2544126B47C5184'
Basically I want the conversion from bigint to varbinary to omit the leading 0 so that it is left out of the string representation.

Try this:
create function dbo.BigintToHex(#X bigint)
returns varchar(20) as
begin
declare #H varchar(20) = ''
declare #D varchar(16) = '0123456789ABCDEF'
if #X = 0
set #H = '0'
if #X < 0
set #H = '-' + dbo.BigintToHex(-#X)
else
while #X > 0
begin
set #H = SUBSTRING(#D,#X % 16+1,1) + #H
set #X = #X / 16
end
return #H
end
go
select dbo.BigintToHex(-167830720612159876)

Related

How to add extremely large numbers in SQL Server

I have numbers in SQL Server that stored in string format
These values are in 0 and 1s only
declare #a varchar(max) = '100101001010100111010001010101011101010110100001010010111001'
declare #b varchar(max) = '010101100101010010101101001010100010100011010000101000100010'
a and b length can reach 100,000 digits
I want to add these 2 variables as numeric
Something like
#a + #b
And the result should be
110202101111110121111102011111111111110121110001111010211011
You can see this is not a binary adding... there are 2s
How can I do this in SQL Server?
I tried this
declare #a varchar(max) = '100101001010100111010001010101011101010110100001010010111001'
declare #b varchar(max) = '010101100101010010101101001010100010100011010000101000100010'
declare #ai bigint = cast(#a as bigint)
declare #bi bigint = cast(#b as bigint)
SELECT #ai + #bi
but I got this error
Msg 8115, Level 16, State 2, Line 4
Arithmetic overflow error converting expression to data type bigint.
Msg 8115, Level 16, State 2, Line 5
Arithmetic overflow error converting expression to data type bigint.
How can I do that?
You'd have to create your own calculator.
Some complicating factors, that the code below takes into consideration:
losing leading zeroes when converting number to string
carry over most significant digit from one batch to the next in case of overflow
For example:
declare #a varchar(max) = '100101001010100111010001010101011101010110100001010010311001'
declare #b varchar(max) = '010101100101010010101101001010100010100011010000101000900010'
declare #e varchar(max) = '110202101111110121111102011111111111110121110001111011211011' -- expected
declare #r varchar(max) = '' -- result
declare #batch_size int -- amount of digits to process at once
set #batch_size=18
declare #sum varchar(19) -- must be bigger than #batch_size
declare #carry bigint
set #carry = 0
declare #length int
set #length = LEN(#a) -- assumes LEN(#a) = LEN(#b)
declare #i int
set #i = #length / #batch_size
if #length % #batch_size = 0
set #i = #i - 1
while #i >= 0 begin
if #i * #batch_size + #batch_size > #length begin
set #a = #a + REPLICATE('0', #batch_size - #length % #batch_size)
set #b = #b + REPLICATE('0', #batch_size - #length % #batch_size)
end
set #sum = CAST(SUBSTRING(#a, #i * #batch_size + 1, #batch_size) AS bigint)
+ CAST(SUBSTRING(#b, #i * #batch_size + 1, #batch_size) AS bigint)
+ #carry
set #carry = 0
if LEN(#sum) > #batch_size begin
set #carry = SUBSTRING(#sum, 1, 1)
set #sum = SUBSTRING(#sum, 2, #batch_size)
end
if LEN(#sum) < #batch_size
set #sum = REPLICATE('0', #batch_size - LEN(#sum)) + #sum
if #i * #batch_size + #batch_size > #length
set #sum = SUBSTRING(#sum, 1, #length - #i * #batch_size)
set #r = #sum + #r
set #i = #i - 1
end
if #carry > 0
print 'overflow error'
if #r <> #e
print 'not the correct result'
select substring(#r,1,#length) as sum_of_a_and_b
You can use FLOAT(53):
declare #a varchar(max) = '100101001010100111010001010101011101010110100001010010111001'
declare #b varchar(max) = '010101100101010010101101001010100010100011010000101000100010'
declare #ai FLOAT(53) = cast(#a as FLOAT(53))
declare #bi FLOAT(53) = cast(#b as FLOAT(53))
The result of SELECT #ai + #b will be 1.1020210111111E+59
This will work for your sample input. But 100.000 digits will be impossible as numeric data type.
db<>fiddle
As your input digits are restricted to 1 and 0 you can do the following.
First create a numbers table with at least as many rows in it as your longest string.
CREATE TABLE dbo.Numbers(Number INT PRIMARY KEY WITH (DATA_COMPRESSION = ROW));
INSERT dbo.Numbers
SELECT TOP 100000 ROW_NUMBER() OVER (ORDER BY ##SPID)
FROM sys.all_columns c1, sys.all_columns c2
And then you can do
declare #a varchar(max) = '100101001010100111010001010101011101010110100001010010111001'
declare #b varchar(max) = '10101100101010010101101001010100010100011010000101000100010'
declare #c varchar(max)
SELECT #c = STRING_AGG(0 + SUBSTRING(normalised.a, Number, 1) + SUBSTRING(normalised.B, Number, 1), '') WITHIN GROUP (ORDER BY Number)
FROM dbo.Numbers
CROSS APPLY(SELECT LEN(#a), LEN(#b)) lengths(len_a, len_b)
/*If #a and #b are not equal length add zeroes to left pad out the shorter one*/
CROSS APPLY (SELECT CONCAT(REPLICATE('0', len_b-len_a),#a), CONCAT(REPLICATE('0', len_a-len_b),#b)) normalised(a,b)
WHERE Number <= LEN(normalised.a)
PRINT #c

SQL byte truncate

My input is a varchar payload (that is actually made of hexadecimal characters). I would like to convert it to bits, then truncate the result to decode it.
I already have a built-in function (hexstrtovarbin) that works correctly and that converts varchars into varbinaries.
For example, for an input "4d", I would like to convert it into bits (01001101) then truncate the first 6 digits, before converting them into an integer (and get eventually 19).
DECLARE #payload varchar(4), #binarypayload binary(1), #converted smallint;
SET #payload = '4d';
SET #binarypayload = hexstrtovarbin(#payload);
SET #converted = CAST(SUBSTRING(#binarypayload, 1, 6) AS int)
If I proceed like this, #converted takes 77 as value. This is because #binarypayload value is "TQ==" (and not actual bits), so the substring does not truncate it.
I have tried to use bit data type, but could not store more than 1 of them.
Would anyone know how to get the actual bits in order to truncate them?
it can be messy but this is my answer, according to your data in the question:
declare #intvalue int
set #intvalue= CONVERT(int, CONVERT(varbinary(max), '4d', 2) )
declare #vsresult varchar(16)
declare #inti int
select #inti = 16, #vsresult = ''
declare #Input varchar(16)
--translating ex string in binary digits
while #inti>0
begin
select #vsresult=convert(char(1), #intvalue % 2)+#vsresult
select #intvalue = convert(int, (#intvalue / 2)), #inti=#inti-1
end
set #Input= left(#vsresult,LEN(#vsresult)-2) -- here your input string without last two digits, 00000000010011
--now return integer value
DECLARE #Cnt tinyint = 1
DECLARE #Len tinyint = LEN(#Input)
DECLARE #Output bigint = CAST(SUBSTRING(#Input, #Len, 1) AS bigint)
WHILE(#Cnt < #Len) BEGIN
SET #Output = #Output + POWER(CAST(SUBSTRING(#Input, #Len - #Cnt, 1) * 2 AS bigint), #Cnt)
SET #Cnt = #Cnt + 1
END
select #Output

SQL REPLACE special characters with value from another table

All,
I am trying to replace the special characters in a string with the URL
encoding values to which they correspond. Below is some example code I have
been working with.
Thanks for the help.
create table #url_encoding_lookup(character varchar(10), code varchar (20))
insert into #url_encoding_lookup (character, code)
values
('!', '%21'),
('"', '%22'),
('#', '%23'),
('$', '%24'),
('%', '%25'),
('&', '%26'),
('''', '%27'),
('(', '%28'),
(')', '%29'),
('*', '%2A'),
('+', '%2B'),
(',', '%2C'),
('-', '%2D'),
('.', '%2E'),
('/', '%2F')
Create table #data
(string varchar (200))
insert into #data
values
('Jim (BoB)'),
('Will''s Place'),
('Auto-Mart')
select * from #data
select * from #url_encoding_lookup
desired results would be
Jim %28Bob%29
Will%27s Place
Auto%2DMart
Create procedure
BEGIN
DECLARE _end BOOLEAN DEFAULT FALSE;
DECLARE _result CHAR(200) DEFAULT str;
DECLARE _find VARCHAR(32);
DECLARE _replace VARCHAR(32);
DECLARE _cur CURSOR FOR SELECT _character, _code FROM url_encoding_lookup;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET _end = TRUE;
OPEN _cur;
_loop: LOOP
FETCH _cur INTO _find, _replace;
IF _end THEN
LEAVE _loop;
END IF;
SET _result = REPLACE(_result, _find, _replace);
END LOOP _loop;
CLOSE _cur;
RETURN _result;
END
Then
SELECT _replace_chars(name) FROM `data`
Result
Jim %28BoB%29
Will%27s Place
Auto%2DMart
ALTER FUNCTION [dbo].[udf_ReplaceYouCoded]
(
#the_string nvarchar(max)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
declare #temp_field nvarchar(max)
create table #url_encoding_lookup(character varchar(10), code varchar (20))
insert into #url_encoding_lookup (character, code)
values
('!', '%21'),
('"', '%22'),
('#', '%23'),
('$', '%24'),
('%', '%25'),
('&', '%26'),
('''', '%27'),
('(', '%28'),
(')', '%29'),
('*', '%2A'),
('+', '%2B'),
(',', '%2C'),
('-', '%2D'),
('.', '%2E'),
('/', '%2F')
declare #x as int
set #x = 1
--LOOP #the_string
while #i < len(#the_string)
if(substring(#the_string,x,1) = (select character from #url_encoding_lookup where character = substring(#the_string,x,1)))
begin
#temp_field = #temp_field + (select code from #url_encoding_lookup where character = substring(#the_string,x,1))
end
else
begin
#temp_field = #temp_field + substring(#the_string,x,1)
end
select #x = #x + 1
end
RETURN #temp_field
END
ALTER function [dbo].[udf_ReplaceSpecialChars]
(#s varchar(256))
returns varchar(256)
as
begin
-- declare #s varchar(256) set #s = 'Jim (P)' --test
if #s is null
return null
declare #s2 varchar(256)
set #s2 = '' --set variable to empty string. ready to recieve values
declare #l int
set #l = len(#s) --determin the number of characters in #s
declare #p int
set #p = 1 --set beginning string position
while #p <= #l begin
declare #c int
set #c = ascii(substring(#s, #p, 1)) --find the ascii number for 1st
character
declare #nc varchar(256)
set #nc = (select code from url_encoding_lookup where ascii_code = #c) --
get corresponding URL encoding string from lookup table
if #c between 33 and 47 or #c between 58 and 64 or #c between 91 and 96
or #c between 123 and 255 --when looping through each character, if special
character
set #s2 = #s2 + #nc --then use string from lookup table
else if #c = 32 or #c between 48 and 57 or #c between 65 and 90 or #c
between 97 and 122 --if character is not special
set #s2 = #s2 + char(#c) --then find char value of character
set #p = #p + 1 --set position to next charachter for loop to look at
end
if len(#s2) = 0
return null
return #s2 --return rebuilt string
end
You can replace the special characters using the following regular expression [\u0100-\uffff]
select regexp_replace(column, '[\u0100-\uffff]', '')

SQL 2008r2 Hex 2 ascii issue

I have an issue converting the following hex string to ascii in tsql:
'd520088000000000000000004000000200000000000003770001c7cc5353482d322e302d4f70656e5353485f352e3570312044656269616e2d347562756e7475340d0a0000034c0614403d6544c243e7535320dc7ab5c3c8de0000007e6469666669652d68656c6c6d616e2d67726f75702d65786368616e67652d7368613235362c6469666669652d68656c6c6d616e2d67726f75702d65786368616e67652d736861312c6469666669652d68656c6c6d616e2d67726f757031342d736861312c6469666669652d68656c6c6d616e2d67726f7570312d73686131000000497373682d7273612d636572742d763030406f70656e7373682e636f6d2c7373682d6473732d636572742d763030406f70656e7373682e636f6d2c7373682d7273612c7373682d6473730000009d6165733132382d6374722c6165733139322d6374722c6165733235362d6374722c617263666f75723235362c617263666f75723132382c6165733132382d6362632c336465732d6362632c626c6f77666973682d6362632c636173743132382d6362632c6165733139322d6362632c6165733235362d6362632c617263666f75722c72696a6e6461656c2d636263406c797361746f722e6c69752e73650000009d6165733132382d6374722c6165733139322d6374722c6165733235362d6374722c617263666f75723235362c617263666f75723132382c6165733132382d6362632c336465732d6362632c626c6f77666973682d6362632c636173743132382d6362632c6165733139322d6362632c6165733235362d6362632c617263666f75722c72696a6e6461656c2d636263406c797361746f722e6c69752e736500000069686d61632d6d64352c686d61632d736861312c756d61632d3634406f70656e7373682e636f6d2c686d61632d726970656d643136302c686d61632d726970656d64313630406f70656e7373682e636f6d2c686d61632d736861312d39362c686d61632d6d64352d393600000069686d61632d6d64352c686d61632d736861312c756d61632d3634406f70656e7373682e636f6d2c686d61632d726970656d643136302c686d61632d726970656d64313630406f70656e7373682e636f6d2c686d61632d736861312d39362c686d61632d6d64352d39360000001a6e6f6e652c7a6c6962406f70656e7373682e636f6d2c7a6c69620000001a6e6f6e652c7a6c6962406f70656e7373682e636f6d2c7a6c69620000000000000000000000000000000000000000'
It should convert to
'? ??????????#??????????w????SSH-2.0-OpenSSH_5.5p1
Debian-4ubuntu4?????L??#=eD?C?SS
?z???????~diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1???Issh-rsa-cert-v00#openssh.com,ssh-dss-cert-v00#openssh.com,ssh-rsa,ssh-dss????aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc#lysator.liu.se????aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc#lysator.liu.se???ihmac-md5,hmac-sha1,umac-64#openssh.com,hmac-ripemd160,hmac-ripemd160#openssh.com,hmac-sha1-96,hmac-md5-96???ihmac-md5,hmac-sha1,umac-64#openssh.com,hmac-ripemd160,hmac-ripemd160#openssh.com,hmac-sha1-96,hmac-md5-96????none,zlib#openssh.com,zlib????none,zlib#openssh.com,zlib????????????????????'
Any ideas? I tried using cast and convert but no success.
Any help is much appreciated.
I am using the below function no outside code - tables are populated by an external application
*
declare #hexstring VARCHAR(8000))
RETURNS VARCHAR(8000)
AS
begin
declare #char1 char(1), #char2 char(1), #strlen int, #currpos int, #result varchar(8000)
set #strlen=len(#hexstring)
set #currpos=1
set #result=''
while #currpos<#strlen
begin
set #char1=substring(#hexstring,#currpos,1)
set #char2=substring(#hexstring,#currpos+1,1)
if (#char1 between '0' and '9' or #char1 between 'A' and 'F')
and (#char2 between '0' and '9' or #char2 between 'A' and 'F')
set #result=#result+
char((ascii(#char1)-case when #char1 between '0' and '9' then 48 else 55 end)*16+
ascii(#char2)-case when #char2 between '0' and '9' then 48 else 55 end)
set #currpos = #currpos+2
end
return #result
end
GO
*
Here is a SQL function that will convert a hex string:
BEGIN
DECLARE #hexstring AS VARCHAR(8000)
SET #hexstring = '4368726973204Ce4747461'
DECLARE #strlen AS INT;
SET #strlen = Len(#hexstring)
DECLARE #currpos AS INT
SET #currpos = 1
DECLARE #hexpos AS VARCHAR(16)
SET #hexpos = '0123456789abcdef'
DECLARE #result AS VARCHAR(8000)
SET #result = ''
DECLARE #ch AS INT
WHILE #currpos < #strlen
BEGIN
SET #ch = CONVERT( INT, 16 * (CHARINDEX( SUBSTRING( #hexstring, #currpos, 1), #hexpos, 1) - 1)
+ (CHARINDEX(SUBSTRING(#hexstring, #currpos+1, 1), #hexpos, 1) - 1))
SET #result = #result + CASE WHEN #ch >= 32 AND #ch < 128 THEN CHAR(#ch) ELSE '?' END
SET #currpos = #currpos + 2
END
SELECT #result
END
I added a short hex string to show the function works.
Your hex string didn't convert so well. It may be because of the nulls in it, so I added the #char >= 32 part to strip out control codes (only convert printable ASCII characters, otherwise insert a ?) and you get a string that looks like the one you are after.
The conversion can be done with a single statement. Since you were using a function I provided my answer as such. Note that this solution requires that the input #hexstring is not prefixed with 0x.
CREATE FUNCTION [dbo].[HexToAscii]
(
#hexstring VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
RETURN CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), #hexstring, 2))
END

Convert integer to hex and hex to integer

So I have this query working (where signal_data is a column) in Sybase but it doesn't work in Microsoft SQL Server:
HEXTOINT(SUBSTRING((INTTOHEX(signal_data)),5,2)) as Signal
I also have it in Excel (where A1 contains the value):
=HEX2DEC(LEFT(DEC2HEX(A1),LEN(DEC2HEX(A1))-2))
Does anyone know how I would do this in SQL Server?
Convert INT to hex:
SELECT CONVERT(VARBINARY(8), 16777215)
Convert hex to INT:
SELECT CONVERT(INT, 0xFFFFFF)
Update 2015-03-16
The above example has the limitation that it only works when the HEX value is given as an integer literal. For completeness, if the value to convert is a hexadecimal string (such as found in a varchar column) use:
-- If the '0x' marker is present:
SELECT CONVERT(INT, CONVERT(VARBINARY, '0x1FFFFF', 1))
-- If the '0x' marker is NOT present:
SELECT CONVERT(INT, CONVERT(VARBINARY, '1FFFFF', 2))
Note: The string must contain an even number of hex digits. An odd number of digits will yield an error.
More details can be found in the "Binary Styles" section of CAST and CONVERT (Transact-SQL). I believe SQL Server 2008 or later is required.
Actually, the built-in function is named master.dbo.fn_varbintohexstr.
So, for example:
SELECT 100, master.dbo.fn_varbintohexstr(100)
Gives you
100 0x00000064
SQL Server equivalents to Excel's string-based DEC2HEX, HEX2DEC functions:
--Convert INT to hex string:
PRINT CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), 16777215),2) --DEC2HEX
--Convert hex string to INT:
PRINT CONVERT(INT,CONVERT(VARBINARY(4),'00FFFFFF',2)) --HEX2DEC
It is possible using the function FORMAT available on SQL Server 2012 and above
select FORMAT(10,'x2')
Results in:
0a
Convert int to hex:
SELECT FORMAT(512+255,'X')
The traditonal 4 bit hex is pretty direct.
Hex String to Integer (Assuming value is stored in field called FHexString) :
CONVERT(BIGINT,CONVERT(varbinary(4),
(SELECT master.dbo.fn_cdc_hexstrtobin(
LEFT(FMEID_ESN,8)
))
))
Integer to Hex String (Assuming value is stored in field called FInteger):
(SELECT master.dbo.fn_varbintohexstr(CONVERT(varbinary,CONVERT(int,
FInteger
))))
Important to note is that when you begin to use bit sizes that cause register sharing, especially on an intel machine, your High and Low and Left and Rights in the registers will be swapped due to the little endian nature of Intel. For example, when using a varbinary(3), we're talking about a 6 character Hex. In this case, your bits are paired as the following indexes from right to left "54,32,10". In an intel system, you would expect "76,54,32,10". Since you are only using 6 of the 8, you need to remember to do the swaps yourself. "76,54" will qualify as your left and "32,10" will qualify as your right. The comma separates your high and low. Intel swaps the high and lows, then the left and rights. So to do a conversion...sigh, you got to swap them yourselves for example, the following converts the first 6 of an 8 character hex:
(SELECT master.dbo.fn_replvarbintoint(
CONVERT(varbinary(3),(SELECT master.dbo.fn_cdc_hexstrtobin(
--intel processors, registers are switched, so reverse them
----second half
RIGHT(FHex8,2)+ --0,1 (0 indexed)
LEFT(RIGHT(FHex8,4),2)+ -- 2,3 (oindex)
--first half
LEFT(RIGHT(FHex8,6),2) --4,5
)))
))
It's a bit complicated, so I would try to keep my conversions to 8 character hex's (varbinary(4)).
In summary, this should answer your question. Comprehensively.
Here is the function for SQL server which converts integer value into its hexadecimal representation as a varchar. It should be easy to adapt to other database types
For example:
SELECT dbo.ToHex(4095) --> FFF
SQL:
CREATE FUNCTION ToHex(#value int)
RETURNS varchar(50)
AS
BEGIN
DECLARE #seq char(16)
DECLARE #result varchar(50)
DECLARE #digit char(1)
SET #seq = '0123456789ABCDEF'
SET #result = SUBSTRING(#seq, (#value%16)+1, 1)
WHILE #value > 0
BEGIN
SET #digit = SUBSTRING(#seq, ((#value/16)%16)+1, 1)
SET #value = #value/16
IF #value <> 0 SET #result = #digit + #result
END
RETURN #result
END
GO
Use master.dbo.fnbintohexstr(16777215) to convert to a varchar representation.
Maksym Kozlenko has a nice solution, and others come close to unlocking it's full potential but then miss completely to realized that you can define any sequence of characters, and use it's length as the Base. Which is why I like this slightly modified version of his solution, because it can work for base 16, or base 17, and etc.
For example, what if you wanted letters and numbers, but don't like I's for looking like 1's and O's for looking like 0's. You can define any sequence this way. Below is a form of a "Base 36" that skips the I and O to create a "modified base 34". Un-comment the hex line instead to run as hex.
declare #value int = 1234567890
DECLARE #seq varchar(100) = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ' -- modified base 34
--DECLARE #seq varchar(100) = '0123456789ABCDEF' -- hex
DECLARE #result varchar(50)
DECLARE #digit char(1)
DECLARE #baseSize int = len(#seq)
DECLARE #workingValue int = #value
SET #result = SUBSTRING(#seq, (#workingValue%#baseSize)+1, 1)
WHILE #workingValue > 0
BEGIN
SET #digit = SUBSTRING(#seq, ((#workingValue/#baseSize)%#baseSize)+1, 1)
SET #workingValue = #workingValue/#baseSize
IF #workingValue <> 0 SET #result = #digit + #result
END
select #value as Value, #baseSize as BaseSize, #result as Result
Value, BaseSize, Result
1234567890, 34, T5URAA
I also moved value over to a working value, and then work from the working value copy, as a personal preference.
Below is additional for reversing the transformation, for any sequence, with the base defined as the length of the sequence.
declare #value varchar(50) = 'T5URAA'
DECLARE #seq varchar(100) = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ' -- modified base 34
--DECLARE #seq varchar(100) = '0123456789ABCDEF' -- hex
DECLARE #result int = 0
DECLARE #digit char(1)
DECLARE #baseSize int = len(#seq)
DECLARE #workingValue varchar(50) = #value
DECLARE #PositionMultiplier int = 1
DECLARE #digitPositionInSequence int = 0
WHILE len(#workingValue) > 0
BEGIN
SET #digit = right(#workingValue,1)
SET #digitPositionInSequence = CHARINDEX(#digit,#seq)
SET #result = #result + ( (#digitPositionInSequence -1) * #PositionMultiplier)
--select #digit, #digitPositionInSequence, #PositionMultiplier, #result
SET #workingValue = left(#workingValue,len(#workingValue)-1)
SET #PositionMultiplier = #PositionMultiplier * #baseSize
END
select #value as Value, #baseSize as BaseSize, #result as Result
Declare #Dato xml
Set #Dato = Convert(xml, '<dato>FF</dato>')
Select Cast( rw.value( 'xs:hexBinary( text()[1])' , 'varbinary(max)' ) as int ) From #Dato.nodes('dato') as T(rw)
The answer by Maksym Kozlenko is nice and can be slightly modified to handle encoding a numeric value to any code format. For example:
CREATE FUNCTION [dbo].[IntToAlpha](#Value int)
RETURNS varchar(30)
AS
BEGIN
DECLARE #CodeChars varchar(100)
SET #CodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
DECLARE #CodeLength int = 26
DECLARE #Result varchar(30) = ''
DECLARE #Digit char(1)
SET #Result = SUBSTRING(#CodeChars, (#Value % #CodeLength) + 1, 1)
WHILE #Value > 0
BEGIN
SET #Digit = SUBSTRING(#CodeChars, ((#Value / #CodeLength) % #CodeLength) + 1, 1)
SET #Value = #Value / #CodeLength
IF #Value <> 0 SET #Result = #Digit + #Result
END
RETURN #Result
END
So, a big number like 150 million, becomes only 6 characters (150,000,000 = "MQGJMU")
You could also use different characters in different sequences as an encrypting device. Or pass in the code characters and length of characters and use as a salting method for encrypting.
And the reverse:
CREATE FUNCTION [dbo].[AlphaToInt](#Value varchar(7))
RETURNS int
AS
BEGIN
DECLARE #CodeChars varchar(100)
SET #CodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
DECLARE #CodeLength int = 26
DECLARE #Digit char(1)
DECLARE #Result int = 0
DECLARE #DigitValue int
DECLARE #Index int = 0
DECLARE #Reverse varchar(7)
SET #Reverse = REVERSE(#Value)
WHILE #Index < LEN(#Value)
BEGIN
SET #Digit = SUBSTRING(#Reverse, #Index + 1, 1)
SET #DigitValue = (CHARINDEX(#Digit, #CodeChars) - 1) * POWER(#CodeLength, #Index)
SET #Result = #Result + #DigitValue
SET #Index = #Index + 1
END
RETURN #Result
Given:
declare #hexStr varchar(16), #intVal int
IntToHexStr:
select #hexStr = convert(varbinary, #intVal, 1)
HexStrToInt:
declare
#query varchar(100),
#parameters varchar(50)
select
#query = 'select #result = convert(int,' + #hb + ')',
#parameters = '#result int output'
exec master.dbo.Sp_executesql #query, #parameters, #intVal output
Below are two functions: dbo.HexToInt and dbo.IntToHex, I use them for such conversion:
if OBJECT_ID('dbo.HexToInt') is not null
drop function dbo.HexToInt
GO
create function dbo.HexToInt (#chars varchar(max))
returns int
begin
declare #char varchar(1), #len int, #i int, #r int, #tmp int, #pow int
set #chars = RTRIM(LTRIM(#chars))
set #len = LEN(#chars)
set #i = 1
set #r = 0
while #i <= #len
begin
set #pow = #len - #i
set #char = SUBSTRING(#chars, #i, 1)
if #char = '0'
set #tmp = 0
else if #char = '1'
set #tmp = 1
else if #char = '2'
set #tmp = 2
else if #char = '3'
set #tmp = 3
else if #char = '4'
set #tmp = 4
else if #char = '5'
set #tmp = 5
else if #char = '6'
set #tmp = 6
else if #char = '7'
set #tmp = 7
else if #char = '8'
set #tmp = 8
else if #char = '9'
set #tmp = 9
else if #char = 'A'
set #tmp = 10
else if #char = 'B'
set #tmp = 11
else if #char = 'C'
set #tmp = 12
else if #char = 'D'
set #tmp = 13
else if #char = 'E'
set #tmp = 14
else if #char = 'F'
set #tmp = 15
set #r = #r + #tmp * POWER(16,#pow)
set #i = #i + 1
end
return #r
end
And the second one:
if OBJECT_ID('dbo.IntToHex') is not null
drop function dbo.IntToHex
GO
create function dbo.IntToHex (#val int)
returns varchar(max)
begin
declare #r varchar(max), #tmp int, #v1 int, #v2 int, #char varchar(1)
set #tmp = #val
set #r = ''
while 1=1
begin
set #v1 = #tmp / 16
set #v2 = #tmp % 16
if #v2 = 0
set #char = '0'
else if #v2 = 1
set #char = '1'
else if #v2 = 2
set #char = '2'
else if #v2 = 3
set #char = '3'
else if #v2 = 4
set #char = '4'
else if #v2 = 5
set #char = '5'
else if #v2 = 6
set #char = '6'
else if #v2 = 7
set #char = '7'
else if #v2 = 8
set #char = '8'
else if #v2 = 9
set #char = '9'
else if #v2 = 10
set #char = 'A'
else if #v2 = 11
set #char = 'B'
else if #v2 = 12
set #char = 'C'
else if #v2 = 13
set #char = 'D'
else if #v2 = 14
set #char = 'E'
else if #v2 = 15
set #char = 'F'
set #tmp = #v1
set #r = #char + #r
if #tmp = 0
break
end
return #r
end
IIF(Fields!HIGHLIGHT_COLOUR.Value="","#FFFFFF","#" & hex(Fields!HIGHLIGHT_COLOUR.Value) & StrDup(6-LEN(hex(Fields!HIGHLIGHT_COLOUR.Value)),"0"))
Is working for me as an expression in font colour
To convert Hex strings to INT, I have used this in the past. It can be modified to convert any base to INT in fact (Octal, Binary, whatever)
Declare #Str varchar(200)
Set #str = 'F000BE1A'
Declare #ndx int
Set #ndx = Len(#str)
Declare #RunningTotal BigInt
Set #RunningTotal = 0
While #ndx > 0
Begin
Declare #Exponent BigInt
Set #Exponent = Len(#Str) - #ndx
Set #RunningTotal = #RunningTotal +
Power(16 * 1.0, #Exponent) *
Case Substring(#str, #ndx, 1)
When '0' then 0
When '1' then 1
When '2' then 2
When '3' then 3
When '4' then 4
When '5' then 5
When '6' then 6
When '7' then 7
When '8' then 8
When '9' then 9
When 'A' then 10
When 'B' then 11
When 'C' then 12
When 'D' then 13
When 'E' then 14
When 'F' then 15
End
Set #ndx = #ndx - 1
End
Print #RunningTotal