Why are HashBytes different - sql-server

When executing that query:
SELECT HashBytes('MD5', CONCAT('A',convert(nvarchar,100),'1234')) as mycol ...
I get HashBytes represented such as
0xA6A0D....
When I do not convert, the HashBytes look like the following:
SELECT HashBytes('MD5', CONCAT('A','100','1234')) as mycol
0x88230...
Why is it different?

As mentioned by Larnu in the comments, data types matter. To see why you're getting different hashes lets take a look at what CONCAT outputs for the two cases:
SELECT CAST(CONCAT('A',convert(nvarchar,100),'1234') AS VARBINARY(MAX));
0x41003100300030003100320033003400
SELECT CAST(CONCAT('A','100','1234') AS VARBINARY(MAX));
0x4131303031323334
Because one of the parameters to CONCAT is of type nvarchar the others are coerced to nvarchar as well to return an nvarchar result.
Read through the Remarks section of the CONCAT (Transact-SQL) documentation for a complete accounting of the expected output types for given input types.

Related

Passing column/variable as binary value to convert function

I am manipulating a large value containing rows and columns values separated with ASCII row and column separators. The result is tabular data which I am inserting in SQL table.
Simple example to get the idea:
George|20;Ivan|15;Peter|10;
is transform to:
George 20
Ivan 15
Peter 10
and inserted in Users ([name], [age]) table.
Before insert, each value is converted to its column type using TRY_CONVERT function. The issue is this does not work as expected with VARBINARY data. For example (the second output is correct):
DECLARE #A NVARCHAR(1024) = '0xFE520676B1A1D93DABAB2319EEA03674F3632EAEEB163D1E88244F5EB1DE10EB';
SELECT TRY_CONVERT(VARBINARY(255), #A)
-- 0x300078004600450035003200300036003700360042003100410031004400390033004400410042004100420032003300310039004500450041003000330036003700340046003300360033003200450041004500450042003100360033004400310045003800380032003400340046003500450042003100440045003100300045004200
SELECT TRY_CONVERT(VARBINARY(255), 0xFE520676B1A1D93DABAB2319EEA03674F3632EAEEB163D1E88244F5EB1DE10EB)
-- 0xFE520676B1A1D93DABAB2319EEA03674F3632EAEEB163D1E88244F5EB1DE10EB
When the VARBINARY data is passed as string, the string is converting itself to VARBINARY. I need to pass the data without quotes, but how to do this when a column/variable of type string is passed?
I needed to use the style option of the TRY_CONVERT function.
DECLARE #A NVARCHAR(1024) = '0xFE520676B1A1D93DABAB2319EEA03674F3632EAEEB163D1E88244F5EB1DE10EB';
-- using style option 1
SELECT TRY_CONVERT(VARBINARY(255), #A, 1)
SELECT TRY_CONVERT(VARBINARY(255), 0xFE520676B1A1D93DABAB2319EEA03674F3632EAEEB163D1E88244F5EB1DE10EB)

SQL Server Converting varchar to datetime

I got a problem in SQL Server with converting a varchar to datetime. I would like to convert/update whole column [datelog] in table:
[dd.mm.yyyy hh:mm:ss]` to `[yyyy-mm-dd hh:mm:ss]
In SQL Server 2012+ you can use PARSE or TRY_PARSE to parse a text value according to a specific culture.
Assuming your text follows the German culture ('de-DE') you can parse it to datetime with :
select PARSE('24.11.2015 13:10:55' as datetime using 'de-DE')
eg:
select PARSE(datelog as datetime using 'de-DE')
The real solution though would be to use the correct field type, ie datetime. It's almost guaranteed that someone, somewhere will either enter text with the wrong format or try to convert the text using the wrong culture.
Date types on the other hand, have no format, they are simply binary values. Using them is faster, safer and easier.
Tricky solution,
DECLARE #inputDate AS VARCHAR(20)='21.11.2015 06:59:00' -- [dd.mm.yyyy hh:mm:ss]
SET #inputDate = REPLACE(#inputDate ,'.' ,'/')
SELECT CONVERT(VARCHAR(24) ,CONVERT(DATETIME ,#inputDate ,103) ,121) OutputDate -- [yyyy-mm-dd hh:mm:ss]
Still you need to change as per your table columns.
temp table with one column of type varchar
create table #temp3 (someDate varchar (30))
insert into #temp3 values ('23.03.1989 15:23:43')
using a combination of concat, substring and right
select concat
(
SUBSTRING(someDate,7,4),'-', SUBSTRING(someDate,4,2),'-',SUBSTRING(someDate,1,2), ' ', right(someDate, 8)
)
from #temp3
gives: 1989-03-23 15:23:43

SQL Server string comparison: nvarchar vs. varchar [duplicate]

I have nvarchar(50) column in SQL Server table and data like this:
123abc
234abc
456abc
My query:
select *
from table
where col like '%abc'
Expected result : all rows should be returned
Actual result: No rows are returned
Works fine if the column is varchar but returns no rows if the type is nvarchar.
Any ideas?
You probably have spaces at the end of your data. Take a look at this example.
Declare #Temp Table(col nvarchar(50))
Insert Into #Temp(col) Values(N'123abc')
Insert Into #Temp(col) Values(N'456abc ')
Select * From #Temp Where Col Like '%abc'
When you run the code above, you will only get the 123 row because the 456 row has a space on the end of it.
When you run the code shown below, you will get the data you expect.
Declare #Temp Table(col nvarchar(50))
Insert Into #Temp(col) Values(N'123abc')
Insert Into #Temp(col) Values(N'456abc ')
Select * From #Temp Where rtrim(Col) Like '%abc'
According to the documentation regarding LIKE in books on line (emphasis mine):
http://msdn.microsoft.com/en-us/library/ms179859.aspx
Pattern Matching by Using LIKE
LIKE supports ASCII pattern matching and Unicode pattern matching. When all arguments (match_expression, pattern, and escape_character, if present) are ASCII character data types, ASCII pattern matching is performed. If any one of the arguments are of Unicode data type, all arguments are converted to Unicode and Unicode pattern matching is performed. When you use Unicode data (nchar or nvarchar data types) with LIKE, trailing blanks are significant; however, for non-Unicode data, trailing blanks are not significant. Unicode LIKE is compatible with the ISO standard. ASCII LIKE is compatible with earlier versions of SQL Server.
for nvarchar type you can use select like this :-
select * from Table where ColumnName like N'%abc%'
Are you sure there are no spaces at the end of the value? You can do this to remove the white space:
select *
from yourTable
where rtrim(yourcolumn) like '%abc'
If you don't want to use the RTRIM and the LIKE together you can also use:
Select *
From yourTable
Where charindex('abc', col) > 0
From Microsoft about using LIKE:
SQL Server follows the ANSI/ISO SQL-92 specification (Section 8.2,
, General rules #3) on how to compare strings
with spaces. The ANSI standard requires padding for the character
strings used in comparisons so that their lengths match before
comparing them. The padding directly affects the semantics of WHERE
and HAVING clause predicates and other Transact-SQL string
comparisons. For example, Transact-SQL considers the strings 'abc' and
'abc ' to be equivalent for most comparison operations.
The only exception to this rule is the LIKE predicate. When the right
side of a LIKE predicate expression features a value with a trailing
space, SQL Server does not pad the two values to the same length
before the comparison occurs. Because the purpose of the LIKE
predicate, by definition, is to facilitate pattern searches rather
than simple string equality tests, this does not violate the section
of the ANSI SQL-92 specification mentioned earlier.
If you know the starting position of the 'abc' string then you can use SUBSTRING:
Select *
From yourTable
Where substring(Col, 4, 3) = 'abc'
But then you can use charindex and substring together and you do not have to worry about white space:
select *
from yourTable
where substring(col, charindex('abc', col), 3) = 'abc'
Your query should work just fine, but you can also try.
SELECT * FROM TABLE WHERE (COL LIKE '%abc%')
In case there are characters you cannot see after the 'abc' part.
This will work fine. You can try.
SELECT *
FROM "table"
WHERE CAST("col" AS VARCHAR) LIKE '%abc'
Just to document some of the ASCII vs Unicode weirdness:
-- ascii like
if 'Non rational ' like 'Non[ --]rational%' print 'like' else print 'not like'
-- unicode like
if N'Non rational ' like N'Non[ --]rational%' print 'like' else print 'not like'
-- unicode like, trailing space removed
if N'Non rational' like N'Non[ --]rational%' print 'like' else print 'not like'
-- unicode like, different wildcard
if N'Non rational ' like N'Non_rational%' print 'like' else print 'not like'
Produces the following:
like
not like
not like
like

Using HashBytes in SQL Server returns different results from DB

I try to calculate md5 hash on a certain value, but I get a weird result.
I run it in two different ways:
SELECT HASHBYTES('md5',ZLA_PASSWORD),ZLA_PASSWORD, len(ZLA_PASSWORD) FROM ZLA_PASSWORD;
SELECT HASHBYTES('md5', '123456');
I get two different results, where only the second one is valid:
0xCE0BFD15059B68D67688884D7A3D3E8C 123456 6
0xE10ADC3949BA59ABBE56E057F20F883E
This is done on an SQL Server 2005.
checking the result of MD5 on 123456 was the same as the second result checking online.
Any ideas?
Thanks!
You have different data types
declare #str1 as varchar(10)
declare #str2 as nvarchar(10)
set #str1 = '123456'
set #str2 = '123456'
select
hashbytes('md5', #str1) as 'varchar',
hashbytes('md5', #str2) as 'nvarchar'
Result
varchar nvarchar
0xE10ADC3949BA59ABBE56E057F20F883E 0xCE0BFD15059B68D67688884D7A3D3E8C
LEN Trims the contents before returning the length (of the trimmed string.)
Most likely your password field is a CHAR field and got whitespace in there.
Try doing a RTRIM before hashing:
SELECT HASHBYTES('md5',RTRIM(ZLA_PASSWORD))
More exactly this should solve the issue:
SELECT HASHBYTES('md5',CAST(ZLA_PASSWORD AS varchar)),ZLA_PASSWORD, len(ZLA_PASSWORD) FROM ZLA_PASSWORD;

SQL 'float' data type, when output as XML, causes undesired float result

You can try simply:
table1: has a column1 of type 'float'
instead of
SELECT column1 from Table1; gives values as seen in table.
Say this returns 15.1
However, if you try
Select column1 from Table1
FOR XML PATH('Table1'), Root('SomeRoot'), TYPE
returns: 1.510000000000000e+001
Has anyone seen this, and how was this fixed?
thanks in advance :)
This is what you get when you work with floating point numbers. You can try this though:
SELECT CONVERT(varchar(100), CAST(column1 AS decimal(38,2)))
you will just need to adjust the precision on the decimal to fit your needs.
Also assuming MSSQL, the str function might fit your needs (MSDN):
select str(column1, 3,1)
It's not necessary to convert the float value into a string to solve this problem.
Just convert the float value into a decimal or a numeric type, with the precision you want.
SELECT CAST(column1 AS decimal(38,2))
or
SELECT CAST(column1 AS numeric(18,5))
When then number will be parsed in XML by Sql Server, it won't be in an exponential form.
This approach is obviously faster than a string conversion (that would occur twice).

Resources