Convert Hexadecimal to INT and vice versa - sql-server

I will be creating a sequential Serial Number made from Hexadecimal values
With this Format:
XX-XX-XX-YYYY
Which XX-XX-XX is default value
And YYYY is the incrementing hexa decimal value
Now to create the serial number based on hex value I need Add 6 to the last generated hex value
MIN: 2D41 + 6 = 2D47
2D47 + 6 ... and so on
MAX: 4100 generation of serial will stop when I meet the MAX value.
I already created it in c# but I need to do it on SQL
int num1 = int.Parse("2D41", NumberStyles.HexNumber); //Convert hex to int
int result = num1 + 6; //Add + 6 for increment
string myHex = result.ToString("X"); //Convert result to hex
MessageBox.Show(myHex); // result 2D47
How can this be done in T-SQL?

DECLARE #x VARBINARY(8) = 0x00002D41;
SELECT CONVERT(VARBINARY(8), CONVERT(INT, #x) + 6);
In order to handle the output as a string:
DECLARE #x VARBINARY(8) = 0x00002D41;
SELECT CONVERT(CHAR(10), CONVERT(VARBINARY(8), CONVERT(INT, #x) + 6), 1);

Hope this helps you
declare #seed varchar(max) = '2D41';
declare #limit varchar(max) = '4100';
select convert(int, convert(varbinary(max), '0x'+#seed,1)),
convert(int, convert(varbinary(max), '0x'+#limit,1));
;with seedlimit(seed, limit) as (
select convert(int, convert(varbinary(max), '0x'+#seed,1)),
convert(int, convert(varbinary(max), '0x'+#limit,1))
)
select SerialNumber = 'XX-XX-XX-' + right(convert(varchar(10),cast(s.seed + 6 * v.number as varbinary(max)),1),4)
from seedlimit s
join master.dbo.spt_values v on type='p'
where s.seed + 6 * v.number <= s.limit;
The basic ingredients are in there for you to create a view/procedure/function out of the answer,
Output:
SerialNumber
-------------
XX-XX-XX-2D41
XX-XX-XX-2D47
...
XX-XX-XX-40F7
XX-XX-XX-40FD

If you already have it in C#, leave it there and simply convert your code to a SQL CLR function.
For a simple example see:
http://blog.sqlauthority.com/2008/10/19/sql-server-introduction-to-clr-simple-example-of-clr-stored-procedure/

Related

Create a custom sequence with letter prefix

I have a sequence in SQL Server
CREATE SEQUENCE dbo.NextBusinessValue
START WITH 1
INCREMENT BY 1 ;
GO
And I'd like to use this to generate a 5 digit custom reference number that uses this sequence to create the number in the format A0000.
The rules for the reference number are that:
1-9999 would be A0001 - A9999
10000-19999 would be B0000 - B9999
20000-29999 would be C0000 - C9999 etc...
It won't ever get the the amount of data that requires going past Z.
I know I can get a letter by using:
SELECT CHAR(65)
So this would work for 1-9999:
declare #n int = 9999
SELECT CHAR(65) + right('0000' + convert(varchar(10), #n), 4)
But would fail when it reaches 10000.
What methods can be used to increment the letter each time the sequence hits the next block of 10000?
UPDATE AND WARNING
Having a primary key and a business key used for display, invoicing is very common. The business key has to be stored and indexed because business users will use it to search for records, documents etc. You shouldn't use the business key as the primary key though.
ORIGINAL
You already get the first digit with #n/10000. Add that to 65 to get the first letter.
To get the remainder you can perform a modulo operation, #n/10000 and format the result as a string:
select char(65 + #n/10000) + format(#n % 10000 ,'d')
Sequences and FORMAT were both introduced in SQL Server 2012, so you can be assured that FORMAT is always available.
9999 will return A9999, 19999 will return B9999 etc.
The scale can be a parameter itself
select char(65 + #n/#scale) + format(#n % #scale ,'d')
Personally I would handle this either in your display code or add it as a computed field either ti the table or view.
This would work upto Z:
declare #n int = 9999
-- Gives A9999
SELECT CHAR(#n / 10000 + 65 ) + right('0000' + convert(varchar(10), #n), 4)
SET #n = 10000
-- Gives B0000
SELECT CHAR(#n / 10000 + 65 ) + right('0000' + convert(varchar(10), #n), 4)
SET #n = 10001
-- Gives B0001
SELECT CHAR(#n / 10000 + 65 ) + right('0000' + convert(varchar(10), #n), 4)
SET #n = 20001
-- Gives C0001
SELECT CHAR(#n / 10000 + 65 ) + right('0000' + convert(varchar(10), #n), 4)
SET #n = 200001
-- Gives U0001
SELECT CHAR(#n / 10000 + 65 ) + right('0000' + convert(varchar(10), #n), 4)
SET #n = 300001
-- Gives _0001
SELECT CHAR(#n / 10000 + 65 ) + right('0000' + convert(varchar(10), #n), 4)
Something like this?
DECLARE #n INT = 9999;
WHILE #n < 26000
BEGIN
SELECT CHAR(65 + CONVERT(INT, #n / 10000)) + RIGHT('0000' + CONVERT(VARCHAR(10), #n), 4);
SELECT #n = #n + 1;
END;
(edited)
You should not use this as primary key, but rather calculate your format for the output on-the-fly. For a faster search I'd reccomend to use the following to calculate a persistant computed column, which you can use with an index.
DECLARE #mockingTbl TABLE(SomeSeqValue INT);
INSERT INTO #mockingTbl VALUES(0),(1),(999),(1000),(9999),(10000),(12345),(50000);
SELECT A.NumeralPart
,B.Rest
,C.StartLetter
,C.StartLetter+REPLACE(STR(A.NumeralPart,4),' ','0') AS YourCode
FROM #mockingTbl AS m
CROSS APPLY(SELECT m.SomeSeqValue % 10000 AS NumeralPart) AS A
CROSS APPLY(SELECT (m.SomeSeqValue-A.NumeralPart)/1000 AS Rest) AS B
CROSS APPLY(SELECT CHAR(B.Rest + ASCII('A'))) AS C(StartLetter)

How can I count number of digits after decimal point

How can I count the number of digits after decimal point in SQL Server 2008?
Eg: 1.99999999495049E-05
I need to know how many digits there are after the decimal point.
If you want to count the number of digits after decimal then the below query works fine.
SELECT LEN(SUBSTRING(cast(COLUMNNAME as varchar), CHARINDEX('.',COLUMNNAME ) + 1, 1000)) AS DIGITSAFTERDECIMALPOINTS
FROM TABLENAME
Hope this helps!
Wow, that's superbly tricky. This sort of logic should get you there:
DECLARE #Value float(53) = 1.99999999495049E-5;
DECLARE #StringValue varchar(40) = CONVERT(varchar(40), #Value, 2);
DECLARE #ELocation int = CHARINDEX('e', #StringValue);
DECLARE #ExponentDigits int = 0 - CAST(SUBSTRING(#StringValue, #Elocation + 1, 40) AS int);
DECLARE #MantissaString varchar(40) = REPLACE(SUBSTRING(#StringValue, 1, #ELocation - 1), '.', '');
DECLARE #NumberOfMantissaDigits int = LEN(CAST(CAST(REVERSE(#MantissaString) AS bigint) AS varchar(20)));
SELECT #ExponentDigits + #NumberOfMantissaDigits - 1 AS NumberOfDecimalPlaces;
I've left them all as separate statements so you can work out what's going on. I could put it all in a single line expression but I'd shudder to try and understand it later.
If you would like to count the number of digits after a decimal point in Teradata
SELECT LENGTH(SUBSTRING(COLUMN_NAME FROM POSITION('.' IN COLUMN_NAME) + 1 FOR 1000))
FROM TABLE

Convert 32 bit binary string of 1's and 0's to Signed Decimal Number in SQL Server

I am using SQL Server 2012 Express. I have a string of 1's and 0's 32 bits in length.
01010010000100010111001101110011
How would I convert that to a Signed Decimal Number in a SQL script?
Currently I use a Web Tool online for my answer, and my current searching is not leading me to the answer I need.
You can perform the conversion with a single T-SQL statement if you use a Tally table:
;WITH Tally(i) AS (
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS i
FROM (VALUES (0), (0), (0), (0), (0), (0), (0), (0)) a(n)
CROSS JOIN (VALUES (0), (0), (0), (0)) b(n)
)
SELECT SUM(t.v) AS DecimalNumber
FROM (
SELECT POWER(CAST(SUBSTRING(x.d, i, 1) AS DECIMAL(10,0)) * 2, 32 - i)
FROM (VALUES ('01010010000100010111001101110011')) x(d)
CROSS JOIN Tally) AS t(v)
Explanation:
Tally is a table expression returning all values from 1-32.
Using these values we can extract every single digit out of the binary string using SUBSTRING.
With the use of POWER mathematical function we can convert every separate binary digit to decimal.
Using SUM we can add up all separate decimal numbers to get the expected result.
Demo here
You can try like below -
DECLARE #Binary VARCHAR(100) = '01010010000100010111001101110011';
DECLARE #characters CHAR(36),
#result BIGINT,
#index SMALLINT,
#base BIGINT;
SELECT #characters = '0123456789abcdefghijklmnopqrstuvwxyz',
#result = 0,
#index = 0,
#base = 2;
WHILE #index < LEN(#Binary)
BEGIN
SELECT #result = #result + POWER(#base, #index) * (CHARINDEX(SUBSTRING(#Binary, LEN(#Binary) - #index, 1), #characters) - 1);
SET #index = #index + 1;
END
SELECT #result;
This will help you to convert from any base ( I used#base as 2 for binary) to base 10. Started from far right and moved to the left until we run out of digits. The conversion is the (base ^ index) * digit.
in Addition to Giorgos Betsos's reply
see ITVF function below:
CREATE FUNCTION [dbo].[udf_BinaryToDecimal]
(
#Binary VARCHAR(31)
)
RETURNS TABLE AS RETURN
WITH Tally (n) AS
(
--32 Rows
SELECT TOP (LEN (#Binary)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1
FROM (VALUES (0),(0),(0),(0)) a(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0)) b(n)
)
SELECT
SUM(SUBSTRING(REVERSE(#Binary),n+1,1) * POWER(2,n)) TenBase
FROM Tally
/*How to Use*/
SELECT TenBase
FROM udf_BinaryToDecimal ('01010010000100010111')
/*Result -> 336151*/
I had to add this code to the end of Abhishek's Code Example to get a Signed number I needed.
DECLARE #MyNewExValue INT
IF #result > 2147483647
BEGIN
SET #result = #result - (2147483648 * 2)
END
SET #MyNewExValue = #result
SELECT #MyNewExValue
This solution will work with binary strings of any (bigint) length:
DECLARE #input varchar(max) =
'01010010000100010111001101110011'
;WITH N(V) AS
(
SELECT
ROW_NUMBER()over(ORDER BY (SELECT 1))
FROM
(VALUES(1),(1),(1),(1))M(a),
(VALUES(1),(1),(1),(1))L(a),
(VALUES(1),(1),(1),(1))K(a)
)
SELECT SUM(SUBSTRING(REVERSE(#input),V,1)*POWER(CAST(2 as BIGINT), V-1))
FROM N
WHERE V <= LEN(#input)
(source)
It should be noted the most upvoted solution above only works with binary strings exactly 32 bits in length, and a string of '00000000000000000000000000000000' returns 1.

Convert INT values to HEX in SQL Server

Alright I am not experienced in SQL Server but anybody here knows how can I transform for example this set of four INT values into this value in HEX?
I have for example:
3533
And I need it converted to:
0x03050303
So for example if I have:
3533 then I get 0x03050303
3459 then I get 0x03040509
Thanks in advance!
Since this is not normal hex conversion, normal tricks won't apply.
The hexadecimal value for the decimal value 3533 is 0xDCD and that's not what you want.
Instead you want each digit of the decimal value separated out into its own byte, so basically you want this:
DEC = abcd
"HEX" = 0a0b0c0d
You can do this with this simple calculation:
DECLARE #VALUE INT = 1234
SELECT CONVERT(VARBINARY(8),
(#VALUE % 10) +
(#VALUE / 10 % 10) * 16*16 +
(#VALUE / 100 % 10) * 16*16*16*16 +
(#VALUE / 1000 % 10) * 16*16*16*16*16*16
) AS X
Output:
01020304
Note that the integer value can be found without the conversion, the conversion above is just to get it formatted like a hex value when testing. "Hex" is just a visual representation, the underlying number is the same.
In other words, the numeric value that corresponds to 0x0a0b0c0d can be found by just:
DECLARE #VALUE INT = 1234
SELECT
((#VALUE % 10) +
(#VALUE / 10 % 10) * 16*16 +
(#VALUE / 100 % 10) * 16*16*16*16 +
(#VALUE / 1000 % 10) * 16*16*16*16*16*16) AS X
The hex output is just a formatted representation.
Use this:
declare #i as int,#str as varchar(20),#counter as int;
set #counter = 1;
set #i = 3459 ;
set #str = '0x'
while (#counter <= len(#i))
begin
set #str = #str + '0' + substring(convert(varchar(20),#i),#counter,1)
set #counter = #counter +1
end
print #str

How to convert integer to text aligning the text on the left?

I need to convert
1
12
145
to (where I use S for SPACE)
SSSS1
SSS12
SS145
If I use CAST (VALUE as CHAR(5)) I get
1SSSS
12SSS
145SS
How to perform that?
SELECT STR(N,5)
FROM (VALUES (1),(12),(145)) T(N)
Returns
-----
1
12
145
RIGHT(' ' + CAST (VALUE as VARCHAR(5)), 5)
More generally:
DECLARE #PadTo tinyint;
SET #PadTo = 5;
SELECT
RIGHT(REPLICATE(' ', #PadTo) + CAST(VALUE as VARCHAR(255)), #PadTo)
...
You can find your ansewer here:
SQL Padding
particularly:
SELECT RIGHT ('000000'+ CAST (#Number AS varchar), 6)
declare #T table(Value int)
insert into #T values (1),(12),(145)
select right(stuff(Value, 1, 0, space(5)), 5)
from #T

Resources