Неожиданное поведение с Oracle ltrim - PullRequest
0 голосов
/ 29 июня 2018
select ltrim('PREPROCESSINGLIST_AOD', 'PREPROCESSINGLIST_') as node_code from dual;

Ожидаемый результат - AOD, но когда я запускаю, меняя первую строку, я получаю неожиданное поведение. Ниже приведены маршруты, которые я пробовал и запустил, изменив характер после _, как BOD, COD...ZOD, а ниже - странный результат.

When    AOD Result==>   AOD
When    BOD Result==>   BOD
When    COD Result==>   D
When    EOD Result==>   D
When    FOD Result==>   FOD
When    GOD Result==>   D
When    HOD Result==>   HOD
When    IOD Result==>   D
When    JOD Result==>   JOD
When    KOD Result==>   KOD
When    LOD Result==>   D
When    MOD Result==>   MOD
When    NOD Result==>   D
When    OOD Result==>   D
When    POD Result==>   D
When    QOD Result==>   QOD
When    ROD Result==>   D
When    SOD Result==>   D
When    TOD Result==>   D
When    UOD Result==>   UOD
When    VOD Result==>   VOD
When    WOD Result==>   WOD
When    XOD Result==>   XOD
When    YOD Result==>   YOD
When    ZOD Result==>   ZOD

И ... Мой вопрос, почему это странное поведение?

Ответы [ 3 ]

0 голосов
/ 29 июня 2018

На вопрос, почему ваш код ведет себя так, уже ответил Лассе Вогстер Карлсен. Чтобы добиться того, что вы хотите, вы можете использовать регулярное выражение:

select regexp_replace('PREPROCESSINGLIST_COD', 
                      '^PREPROCESSINGLIST_', 
                      '') as node_code 
from dual;

Это удалит ведущий PREPROCESSINGLIST из строки, но оставит его там, если он находится в середине строки (из-за привязки ^ для начала строки).

0 голосов
/ 29 июня 2018

если я вообще хочу использовать подстроку после _, что лучше использовать?

Не совсем понятно, хотите ли вы удалить только точную строку 'PREPROCESSINGLIST_', и если да, то должно ли это совпадать только в начале строки или где-либо еще; или вы хотите удалить что-либо до первого подчеркивания или что-нибудь до любого подчеркивания.

В зависимости от ваших фактических данных и результата, который вы хотите получить, вы можете использовать regexp_replace(), как показывал @FrankScmitt (с или без привязки), или просто replace(), или комбинацию instr() и substr().

С некоторыми подготовленными данными с различными шаблонами, предоставленными в CTE:

with t (str) as (
            select 'PREPROCESSINGLIST_AOD' from dual
  union all select 'PREPROCESSINGLIST_BOD' from dual
  union all select 'PREPROCESSINGLIST_COD' from dual
  union all select 'PREPROCESSINGLIST_DOD' from dual
  union all select 'XYZ_PREPROCESSINGLIST_EOD' from dual
  union all select 'XYZ_FOD' from dual
  union all select 'ABC_XYZ_GOD' from dual
  union all select 'HOD' from dual
)
select str,
  regexp_replace(str, '^PREPROCESSINGLIST_', null) as anchor_regex,
  regexp_replace(str, 'PREPROCESSINGLIST_', null) as free_regex,
  replace(str, 'PREPROCESSINGLIST_', null) as free_replace,
  case when instr(str, '_') > 0 then substr(str, instr(str, '_') + 1) else str end
    as first_underscore,
  case when instr(str, '_') > 0 then substr(str, instr(str, '_', -1) + 1) else str end
    as last_underscore
from t;

STR                       ANCHOR_REGEX              FREE_REGEX  FREE_REPLAC FIRST_UNDERSCORE      LAST_UNDERS
------------------------- ------------------------- ----------- ----------- --------------------- -----------
PREPROCESSINGLIST_AOD     AOD                       AOD         AOD         AOD                   AOD        
PREPROCESSINGLIST_BOD     BOD                       BOD         BOD         BOD                   BOD        
PREPROCESSINGLIST_COD     COD                       COD         COD         COD                   COD        
PREPROCESSINGLIST_DOD     DOD                       DOD         DOD         DOD                   DOD        
XYZ_PREPROCESSINGLIST_EOD XYZ_PREPROCESSINGLIST_EOD XYZ_EOD     XYZ_EOD     PREPROCESSINGLIST_EOD EOD        
XYZ_FOD                   XYZ_FOD                   XYZ_FOD     XYZ_FOD     FOD                   FOD        
ABC_XYZ_GOD               ABC_XYZ_GOD               ABC_XYZ_GOD ABC_XYZ_GOD XYZ_GOD               GOD        
HOD                       HOD                       HOD         HOD         HOD                   HOD        

Если вы можете получить нужный результат более чем одним способом, то, как правило, более эффективно избегать регулярных выражений, но иногда они являются единственным (вменяемым) выбором. Как всегда, лучше самим проверить варианты на основе фактических данных, чтобы увидеть, что является наиболее эффективным или хотя бы достаточно эффективным.

0 голосов
/ 29 июня 2018

Это не странное поведение. Это задокументированное поведение.

Согласно документации LTRIM :

LTRIM удаляет из левого конца char все символы, содержащиеся в set .

Таким образом, второй параметр, хотя и в строке type , не является строкой как таковой, он представляет собой набор символов для удаления.

Так вот:

ltrim('PREPROCESSINGLIST_COD', 'PREPROCESSINGLIST_')

в конечном итоге вернет D, потому что C и O находятся в PREPROCESSINGLIST_:

PREPROCESSINGLIST_
     ^^
     here

_AOD, однако, A не входит в комплект, поэтому обрезка на этом останавливается.

Если вы протестируете, вы увидите, что вы получаете точно такое же поведение из этого:

ltrim('PREPROCESSINGLIST_COD', 'CEGILNOPRST_')

Это должны быть те же символы, что и в PREPROCESSINGLIST_.

...