Is it possible to generate hash code from both database server and compare them? How to write the following pseudo SQL in SQL Server? Especially the two getHash
functions which accept mutliple numeric/float columns in SQL server and oracle.
select s.PK
from sqltable s
join openquery(oracleLinkedServer,
'select PK, getHash(Column1, floatColumn2, ..., floatColumnN) oracleHash
from oracleTable') o on o.PK = s.PK
where
getHash(Column1, floatColumn2, ..., floatColumnN) <> oracleHash
In SQL Server you have hashbytes(); in Oracle you have DBMS_CRYPTO.Hash(). You should be able to use them to calc an MD5 hash on both sides, though I am not positive the hashes will match... its worth a shot.
There are other ways to compare tables but to answer your question these are the two native functions on either platform.
You can use
CHECKSUM()
in SQL Server to compute a multi-column hash.In SQL Server:
result:
In Oracle :
result:
Make sure your strings are exactly the same (case sensitive). Here I used 'A' as a simple example, but it could be any string really.
If you avoid data type differences by converting to a big string, you should be able to produce the same md5 hash on different platforms. Note that SQL Server prepended a '0x' to the hash to denote hex representation, which I stripped with the substring.
If you have limited access to the Oracle system, and haven't been granted execute permissions on
DBMS_CRYPTO.Hash()
, you can still useDBMS_OBFUSCATION_TOOLKIT.MD5()
to generate the same hashed value on both Oracle and SQL Server. You just have to make sure to convert the string to the same code page as the machine running SQL Server. I believe the default on most North American Windows boxes iswindows-1252 ANSI Latin 1; Western European (Windows)
(from https://docs.microsoft.com/en-us/windows/desktop/intl/code-page-identifiers)I don't particularly like having function calls in my
WHERE
clauses, so I put the SQL side hash into a CTE, and then join to theOPENQUERY
results.A couple of things to point out here that might not be immediately apparent.
First, I'm adding a pipe character,
|
, between each column in the concatenated text. This is differentiate combinations like"digital" + "aaron"
and"digi" + "talaaron"
from producing the same hash, as the string would become"digital|aaron"
and"digi|talaaron"
which should produce different hashed values.Second, when we get the SQL side has in the CTE, the value comes back as a
VARBINARY
. If we just displayed this value, there would be a leading0x
. But we want to strip this off, and also convert the value to something a bit more useful than aVARBINARY
. So we convert toCHAR(32)
with a style of2
.