Контрольная сумма строки с использованием ora_hash дает разные результаты для разных пользователей - PullRequest
0 голосов
/ 26 октября 2018

Попытка сгенерировать уникальную контрольную сумму для строки данных в таблице Oracle, для использования в целях обеспечения того, чтобы строка не изменялась между двумя пользователями, получающими их, и пыталась обновить их одновременно.

 SELECT ora_hash( KY_REFUND_ID CD_STATUS || KY_CHECK_NUM || 
        COMMENT || CREATED_BY || TS_CREATED || TX_UPDATED_BY || TS_UPDATED) as checksum
 INTO p_checksum
 FROM REFUND_CHECKS r
 WHERE ROWID = p_rowid;

Странно, мы получаем другую контрольную сумму, если процедура вызывается в sqldeveloper при отладке, в отличие от вызова через веб-сайт.Это становится проблемой, когда контрольная сумма снова вычисляется внутренне для сравнения с моим значением - у меня получено 12345, но внутренне те же самые данные дают 78904, поэтому система говорит, что они не совпадают.

Насколько яКак видите, единственный способ, когда два разных пользователя получают разные контрольные суммы при просмотре одних и тех же данных ... это то, что они не смотрят на одни и те же данные.Я подозреваю, что между этими двумя вызовами есть нечто невидимое.И единственное, что я вижу, это то, что аккаунт используется.

В sqldeveloper вызов выполняется с использованием имени схемы, но веб-сайт вызывает как dotnet_user.

В любом случае имя учетной записи используется в качестве некоторого дополнительного значения в математике, когдаопределение контрольной суммы?Если нет, то какие еще могут быть невидимые различия, которые могут привести к различным результатам, и, что более важно, как они могут быть стандартизированы, чтобы обе стороны получили одинаковый результат?

1 Ответ

0 голосов
/ 26 октября 2018

Проблема в том, что вы полагаетесь на неявное преобразование.Вы генерируете строку, объединяя несколько значений вместе, что означает, что столбцы меток времени (предположительно, из имен) неявно преобразуются в строки с использованием настроек NLS сеанса.И у вас есть разные настройки NLS в SQL Developer и через веб-клиент.

В качестве простой демонстрации:

alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS';

select ora_hash(timestamp '2018-01-01 00:00:00') as ts_hash,
       'abc' || timestamp '2018-01-01 00:00:00' as str,
       ora_hash('abc' || timestamp '2018-01-01 00:00:00') as str_hash
from dual;

   TS_HASH STR                      STR_HASH
---------- ---------------------- ----------
1986439397 abc2018-01-01 00:00:00  588765268

alter session set nls_timestamp_format = 'DD-Mon-YYYY HH:MI:SS AM';

select ora_hash(timestamp '2018-01-01 00:00:00') as ts_hash,
       'abc' || timestamp '2018-01-01 00:00:00' as str,
       ora_hash('abc' || timestamp '2018-01-01 00:00:00') as str_hash
from dual;

   TS_HASH STR                          STR_HASH
---------- -------------------------- ----------
1986439397 abc01-Jan-2018 12:00:00 AM 2809284723

То же значение временной метки и тот же хэш самой метки времени в его собственных данныхтип;но разные неявные преобразования в строки и, таким образом, разные хэши этих строк.

Измените код, чтобы явно преобразовывать метки времени в определенный фиксированный формат, и он больше не будет полагаться на NLS, и поэтому станет согласованным, например

 SELECT ora_hash( KY_REFUND_ID CD_STATUS || KY_CHECK_NUM || 
          COMMENT || CREATED_BY ||
          to_char(TS_CREATED, 'SYYYYMMDDHH24MISSFF9') || TX_UPDATED_BY ||
          to_char(TS_UPDATED, 'SYYYYMMDDHH24MISSFF9')) as checksum
 INTO p_checksum
 FROM REFUND_CHECKS r
 WHERE ROWID = p_rowid;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...