Error converting VarChar to VarBinary in SQL Server - sql

I need to convert varchar to varbinary. The query I'm using is working correctly for only some values.
This one is working fine
SELECT CONVERT (VARBINARY(MAX), 'AFE27AF97DC6', 2)
while this one throws an error
Error converting data type varchar to varbinary
SELECT CONVERT (VARBINARY(MAX), 'AFEE27AF97DC6', 2)
I need to use style 2.
I've read all the similar questions but I couldn't find the solution. Any thought would help me. Thank you!

Hmm, AFEE27AF97DC6 is one nibble short and it seems like only full bytes are accepted. Try to zero pad it. E.g.
SELECT convert(varbinary(max), '0AFEE27AF97DC6', 2)
You can also wrap it in a CASE expression checking if the string has an even or odd length, should the strings be variable.
SELECT convert(varbinary(max),
CASE
WHEN len('AFEE27AF97DC6') % 2 <> 0 THEN
concat('0', 'AFEE27AF97DC6')
ELSE
'AFEE27AF97DC6'
END,
2)
(Replace the literals with your variable.)

This is pretty clearly stated in the documentation:
1, 2 [for the third argument]
For a binary data_type, the expression must be a character expression. The expression must have an even number of hexadecimal digits (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, a, b, c, d, e, f).
Your first string has a length of 12, so it converts fine. The second has a length of 13, so it is not valid.
I am not sure what you intend, but a 0 in the 3rd position gives similar results for the two conversions:
SELECT CONVERT(varbinary(max),'AFE27AF97DC6' , 2), CONVERT(varbinary(max),'AF0EE27AF97DC6' , 2)
Gives:
0xAFE27AF97DC6 0xAF0EE27AF97DC6

Related

Problem with using SUBSTRING and CHARINDEX

I have a column (RCV1.ECCValue) in a table which 99% of the time has a constant string format- example being:
T0-11.86-273
the middle part of the two hyphens is a percentage. I'm using the below sql to obtain this figure which is working fine and returns 11.86 on the above example. when the data in that table is in above format
'Percentage' = round(SUBSTRING(RCV1.ECCValue,CHARINDEX('-',RCV1.ECCValue)+1, CHARINDEX('-',RCV1.ECCValue,CHARINDEX('-',RCV1.ECCValue)+1) -CHARINDEX('-',RCV1.ECCValue)-1),2) ,
However...this table is updated from an external source and very occasionally the separators differ, for example:
T0-11.86_273
when this occurs I get the error:
Invalid length parameter passed to the LEFT or SUBSTRING function.
I'm very new to SQL and have got myself out of many challenges but this one has got me stuck. Any help would be mostly appreciated. Is there a better way to extract this percentage value?
Replace '_' with '-' to string in CHARINDEX while specifying length to the substring
'Percentage' = round(SUBSTRING(RCV1.ECCValue,CHARINDEX('-',RCV1.ECCValue)+1, CHARINDEX('-',replace(RCV1.ECCValue,'_','-'),CHARINDEX('-',RCV1.ECCValue)+1) -CHARINDEX('-',RCV1.ECCValue)-1),2) ,
If you can guarantee the structure of these strings, you can try parsename
select round(parsename(translate(replace('T0-11.86_273','.',''),'-_','..'),2), 2)/100
Breakdown of steps
Replace . character in the percentage value with empty string using replace.
Replace - or _, whichever is present, with . using translate.
Parse the second element using parsename.
Round it up to 2 digits, which will also
automatically cast it to the desired numeric type.
Divide by 100
to restore the number as percentage.
Documentation & Gotchas
Use NULLIF to null out such values
round(
SUBSTRING(
RCV1.ECCValue,
NULLIF(CHARINDEX('-', RCV1.ECCValue), 0) + 1,
NULLIF(CHARINDEX('-',
RCV1.ECCValue,
NULLIF(CHARINDEX('-', RCV1.ECCValue), 0) + 1
), 0)
- NULLIF(CHARINDEX('-', RCV1.ECCValue), 0) - 1
),
2)
I strongly recommend that you place the repeated values in CROSS APPLY (VALUES to avoid having to repeat yourself. And do use whitespace, it's free.

Prevent ORA-01722: invalid number in Oracle

I have this query
SELECT text
FROM book
WHERE lyrics IS NULL
AND MOD(TO_NUMBER(SUBSTR(text,18,16)),5) = 1
sometimes the string is something like this $OK$OK$OK$OK$OK$OK$OK, sometimes something like #P,351811040302663;E,101;D,07112018134733,07012018144712;G,4908611,50930248,207,990;M,79379;S,0;IO,3,0,0
if I would like to know if it is possible to prevent ORA-01722: invalid number, because is some causes the char in that position is not a number.
I run this query inside a procedure a process all the rows in a cursor, if 1 row is not a number I can't process any row
You could use VALIDATE_CONVERSION if it's Oracle 12c Release 2 (12.2),
WITH book(text) AS
(SELECT '#P,351811040302663;E,101;D,07112018134733,07012018144712;G,4908611,50930248,207,990;M,79379;S,0;IO,3,0,0'
FROM DUAL
UNION ALL SELECT '$OK$OK$OK$OK$OK$OK$OK'
FROM DUAL
UNION ALL SELECT '12I45678912B456781234567812345671'
FROM DUAL)
SELECT *
FROM book
WHERE CASE
WHEN VALIDATE_CONVERSION(SUBSTR(text,18,16) AS NUMBER) = 1
THEN MOD(TO_NUMBER(SUBSTR(text,18,16)),5)
ELSE 0
END = 1 ;
Output
TEXT
12I45678912B456781234567812345671
Assuming the condition should be true if and only if the 16-character substring starting at position 18 is made up of 16 digits, and the number is equal to 1 modulo 5, then you could write it like this:
...
where .....
and case when translate(substr(text, 18, 16), 'z0123456789', 'z') is null
and substr(text, 33, 1) in ('1', '6')
then 1 end
= 1
This will check that the substring is made up of all-digits: the translate() function will replace every occurrence of z in the string with itself, and every occurrence of 0, 1, ..., 9 with nothing (it will simply remove them). The odd-looking z is needed due to Oracle's odd implementation of NULL and empty strings (you can use any other character instead of z, but you need some character so no argument to translate() is NULL). Then - the substring is made up of all-digits if and only if the result of this translation is null (an empty string). And you still check to see if the last character is 1 or 6.
Note that I didn't use any regular expressions; this is important if you have a large amount of data, since standard string functions like translate() are much faster than regular expression functions. Also, everything is based on character data type - no math functions like mod(). (Same as in Thorsten's answer, which was only missing the first part of what I suggested here - checking to see that the entire substring is made up of digits.)
SELECT text
FROM book
WHERE lyrics IS NULL
AND case when regexp_like(SUBSTR(text,18,16),'^[^a-zA-Z]*$') then MOD(TO_NUMBER(SUBSTR(text,18,16)),5)
else null
end = 1;

Why does it give an error when casting a string to GUID in SQL Server?

This is a simple issue.. I have two statements in sql server:
Case 1) select cast('d8b673a9-816c-4f45-b446-158b3e65fb45' as uniqueidentifier)
**Result in this case:**
D8B673A9-816C-4F45-B446-158B3E65FB45
Case 2) select cast('g448d9e5-1499-25dc-er45-254717c234g8' as uniqueidentifier)
**Result in this case:**
Conversion failed when converting from a character string to uniqueidentifier.
As you can see there is clearly no difference between the two guids..
A GUID should not contain an 'r' or a 'g',only Hexadecimal digits, which is why your second string will not cast.
See info here:
https://en.wikipedia.org/wiki/Hexadecimal
In mathematics and computing, hexadecimal (also base 16, or hex) is a positional numeral system with a radix, or base, of 16. It uses sixteen distinct symbols, most often the symbols 0–9 to represent values zero to nine, and A, B, C, D, E, F (or alternatively a, b, c, d, e, f) to represent values ten to fifteen.

Why TSQL convert a function's result in one way and a character string to other way?

I try this command in SQL Server 2005 to obtain a MD5 from '123':
select SUBSTRING(sys.fn_sqlvarbasetostr(HASHBYTES('MD5', '123' )), 3, 32)
and I get this result:
202cb962ac59075b964b07152d234b70
I want to convert to binary format,
select
convert(varbinary(16), SUBSTRING(sys.fn_sqlvarbasetostr(HASHBYTES('MD5', '123')), 3, 32))
And I get this result:
0x32003000320063006200390036003200
Why does this code:
select convert(varbinary(16), '202cb962ac59075b964b07152d234b70')
result in a different value?
0x32303263623936326163353930373562
"Regular Character Type" vs Unicode
This performs a conversion from Nvarchar(Unicode) to Varbinary
select convert(varbinary(16),SUBSTRING(sys.fn_sqlvarbasetostr(HASHBYTES('MD5', '123' )),3,32))
By default, putting text in single quotes uses regular character types like Char or Varchar. This performs a conversion from Varchar("Regular Data Type") to Varbinary
select convert(varbinary(16),'202cb962ac59075b964b07152d234b70')
Try this:
SELECT CONVERT(varbinary(16), N'202cb962ac59075b964b07152d234b70')
The "N" before the quote defines the value as Nvarchar(Unicode) and you get your desired value
0x32003000320063006200390036003200
Hope this helps!

How to set a string value into varbinary

I'm using SQL Server and I'm trying to set a string into a varbinary without converting its value.
Example:
declare #string varchar(max)
set #string='0x7777'
update tablename
set Data=#string
I know this is not possible since it's not allowed. However I don't wanna convert the string to varbinary (using select CONVERT(varbinary(max),#string)) since it'll result in saving:
0x307837373737
Also, I know that making #string varbinary and removing ' 's would fix the problem, however that's not what I'm looking for since I'm working with strings in order to save it inside a varbinary.
I want the output to be: 0x7777 inside the varbinary
Thank you.
You can use CONVERT, just pass 3rd parameter.
update tablename
set Data=convert(varbinary(max), #string, 1)
If the data_type is a binary type, the expression must be a character
expression. The expression must be composed of an even number of
hexadecimal digits (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, a,
b, c, d, e, f). If the style is set to 1 the characters 0x must be the
first two characters in the expression. If the expression contains an
odd number of characters or if any of the characters are invalid an
error is raised.
See reference for binary styles conversion.