Как сравнить однобайтовые и многобайтовые строки? - PullRequest
0 голосов
/ 31 мая 2018

У меня есть две строки, одна из которых вводится клиентом, а другая - данные в таблице.Две строки кажутся одинаковыми, но имеют разное шестнадцатеричное значение, когда я пытаюсь CAST_TO_RAW.

SELECT UTL_RAW.CAST_TO_VARCHAR2('3539352F47502D0A41544258484E') INPUT,
       UTL_RAW.CAST_TO_NVARCHAR2('003500390035002F00470050002D000D000A00410054004200580048004E') DTA
  FROM DUAL;
/*input and data seem same*/

Учтите, что две строки одинаковы.Как я передаю этот случай и сравниваю их в запросе следующим образом:

SELECT A.DATA,
       A.ORTHER_COL
  FROM MYTABLE A
 WHERE A.DATA = INPUT;

Я пытался TO_SINGLE_BYTE, но он не работает (из-за различных LENGTHB):

SELECT *
  FROM DUAL
 WHERE TO_SINGLE_BYTE(UTL_RAW.CAST_TO_VARCHAR2('3539352F47502D0A41544258484E')) =
       TO_SINGLE_BYTE(UTL_RAW.CAST_TO_NVARCHAR2('003500390035002F00470050002D000D000A00410054004200580048004E'));
/*return null*/

1 Ответ

0 голосов
/ 31 мая 2018

Две строки не совпадают;второй имеет дополнительный 000D в середине:

'3539352F47502D0A41544258484E'
             ^^^^
'003500390035002F00470050002D000D000A00410054004200580048004E'
                           ^^  ^^  ^^

Если бы они были на самом деле одинаковыми, вы могли бы сравнить их с неявным преобразованием (добавив 0D к первой строке, но вы можете предпочестьчтобы удалить его из второго):

SELECT *
  FROM DUAL
 WHERE UTL_RAW.CAST_TO_VARCHAR2('3539352F47502D0D0A41544258484E') =
       UTL_RAW.CAST_TO_NVARCHAR2('003500390035002F00470050002D000D000A00410054004200580048004E');

D
-
X

Или явно cat для nvarchar2:

SELECT *
  FROM DUAL
 WHERE cast(UTL_RAW.CAST_TO_VARCHAR2('3539352F47502D0D0A41544258484E') as nvarchar2(2000)) =
       UTL_RAW.CAST_TO_NVARCHAR2('003500390035002F00470050002D000D000A00410054004200580048004E');

D
-
X

или другим способом:

SELECT *
  FROM DUAL
 WHERE UTL_RAW.CAST_TO_VARCHAR2('3539352F47502D0D0A41544258484E') =
       cast(UTL_RAW.CAST_TO_NVARCHAR2('003500390035002F00470050002D000D000A00410054004200580048004E') as varchar2(4000));

D
-
X

Это возможноя думаю, вы могли видеть некоторые странности в приведении, в зависимости от необработанных данных и двух наборов символов БД.


Из Oracle 12c вы могли бы потенциально использовать лингвистическое сопоставление UCA , которое игнорирует разницу между LF и CRLF, например:

alter session set nls_sort = 'UCA0700_ORADUCET_S1';
alter session set nls_comp = 'LINGUISTIC';

SELECT *
  FROM DUAL
 WHERE UTL_RAW.CAST_TO_VARCHAR2('3539352F47502D0A41544258484E') =
       UTL_RAW.CAST_TO_NVARCHAR2('003500390035002F00470050002D000D000A00410054004200580048004E');

D
-
X

Вам нужно будет посмотреть, как это повлияет на производительность, и будут ли другие игнорируемые символы вызывать ложные совпадения.Если вы только хотите игнорировать несоответствия между LF / CRLF, то вы, вероятно, застряли в санации данных для обеспечения согласованности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...