当datetime与文本连接时,oracle错误地派生md5

oiopk7p5  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(347)

请考虑oracle 12c上的此sql

select to_date('01-02-2020','MM-DD-YYYY'),
standard_hash (to_date('01-02-2020','MM-DD-YYYY'), 'MD5') Only_Date_MD5,
to_date('01-02-2020 12:34:56','MM-DD-YYYY HH:MI:SS'),
standard_hash (to_date('01-02-2020 12:34:56','MM-DD-YYYY HH:MI:SS'), 'MD5') DateTime_MD5,
standard_hash (to_date('01-02-2020','MM-DD-YYYY') || 'SomeText', 'MD5') Date_Concat_Text_MD5,
standard_hash (to_date('01-02-2020 12:34:56','MM-DD-YYYY HH:MI:SS') || 'SomeText', 'MD5') DateTime_Concat_Text_MD5
from dual;

输出

SOME_DATE                   01/02/2020
ONLY_SOME_DATE_MD5          6D44D021F4D2CACA3DBEC6E88AEEB7AD
SOME_DATETIME               01/02/2020 12:34:56
SOME_DATETIME_MD5           F8FDBBC5181E79B99A1EE13CB71A1D46
DATE_CONCAT_TEXT_MD5      **FE7DA8E96A7233A33F03CC592A929011**
DATETIME_CONCAT_TEXT_MD5  **FE7DA8E96A7233A33F03CC592A929011**

为什么oraclemd5返回相同的值来表示连接了文本的日期和连接了相同文本的datetime(具有相同日期)。它在派生md5时丢弃datetime的时间部分。

wfypjpf4

wfypjpf41#

这与 standard_hash() . 问题是一个 date 一根绳子。
当你转换一个 date 隐式到字符串(或使用 to_char() 如果没有格式),则结果只是日期部分。因此:

select to_date('01-02-2020 12:34:56', 'MM-DD-YYYY HH:MI:SS') || 'abc'
from dual

退货:

02-JAN-20abc

出于您的目的,我强烈建议您使用 to_char() 转换回更详细的表示。你也可以用 to_timestamp() 取而代之的是——默认表示将包括时间。
所以:

select to_timestamp('01-02-2020 12:34:56', 'MM-DD-YYYY HH:MI:SS') || 'abc'
from dual

退货:

02-JAN-20 12.34.56.000000000abc
k3bvogb1

k3bvogb12#

计算具有不同数据类型(这不可避免地导致数据类型转换)的串联列的哈希码的一个良好实践(或可能是一种变通方法)是在此步骤之前显式地将nls设置设置为最覆盖的选项。
例子

ALTER SESSION SET NLS_NUMERIC_CHARACTERS = ',.';
ALTER SESSION SET NLS_DATE_FORMAT = 'DD.MM.YYYY HH24:MI:SS';
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'DD.MM.YYYY HH24:MI:SSXFF';
ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = 'DD.MM.YYYY HH24:MI:SSXFF TZR';

这将1)不消耗转换中的某些数据部分,2)产生独立于会话设置的确定结果。
您可能需要存储以前的值,并在连接之后恢复它们。
此步骤将确保样本数据的预期结果。
您应该考虑的另一件事是使用一个特殊的连接分隔符(数据中没有出现的字符串)
例子

col1||chr(10)||col1

这将确保两行 col1 NULL, col2 'A' 以及 col1 'A', col2 NULL 将在串联后生成不同的哈希代码。

相关问题