0
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

而且......我的问题为什么会出现这种奇怪的行为?

4

3 回答 3

4

这不是奇怪的行为。这是记录在案的行为。

根据LTRIM 的文档

LTRIM从char的左端删除set中包含的所有字符。

所以第二个参数虽然是字符串类型,但不是字符串本身,它是一组要修剪的字符。

所以这:

ltrim('PREPROCESSINGLIST_COD', 'PREPROCESSINGLIST_')

最终会返回D,因为CO都在PREPROCESSINGLIST_

PREPROCESSINGLIST_
     ^^
     here

_AOD但是,A不在集合中,因此修剪在此停止。

如果您进行测试,您可以看到您从中得到完全相同的行为:

ltrim('PREPROCESSINGLIST_COD', 'CEGILNOPRST_')

这应该与 中的字符相同PREPROCESSINGLIST_

于 2018-06-29T12:57:39.857 回答
3

if at all I just want the substring after _, what should be best to use?

It isn't quite clear if you want to only remove the exact string 'PREPROCESSINGLIST_', and if so whether that should only be matched at the start of the string or anywhere; or you want to remove anything up to the first underscore, or anything up to any underscore.

Depending on your actual data and the result you want to get, you can use regexp_replace() as @FrankScmitt showed (with or without an anchor), or a plain replace(), or a combination of instr() and substr().

With some made-up data with various patterns provided in a 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        

If you can get the result you need in more than one way then it is generally more efficient to avoid regular expressions, but sometimes they are the only (sane) choice. As always it's best to test the options yourself against your actual data to see what is most efficient - or at least efficient enough.

于 2018-06-29T14:05:59.017 回答
3

Lasse Vågsæther Karlsen 已经回答了为什么您的代码会以这种方式运行的问题。要实现您想要的,您可以使用正则表达式:

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

这将从字符串中删除前导PREPROCESSINGLIST,但如果它位于字符串的中间,则将其保留在那里(因为字符串^开头的锚点)。

于 2018-06-29T13:01:16.570 回答