Oracle SQL - 如何使用 SUBSTR 从字符串中删除字符?

Oracle SQL - How to Cut out characters from a string with SUBSTR?

我在我需要的特定列中有 "ABC1234", "ABC", "DEF456", "GHI" 等值。

现在我需要拆分这个字符串,但前提是字符(例如 "ABC")后跟数字。

因此,如果值为 "ABC1234",那么我需要将 ABC 和 1234 分开。但是如果只有 "ABC" 作为值,我只需要 "ABC"。我找不到 SUBSTR 的任何解决方案。你有什么想法吗?

注意:字符的长度可以从 1 到 10 不等,也可以是数字的长度(有时没有像我给你展示的那样)。

这样的事情行吗?

SQL> with test (col) as
  2    (select '"ABC1234", "ABC", "dEf456", "123GHI", "456"' from dual),
  3  inter as
  4    (select trim(regexp_substr(replace(col, '"', ''), '[^,]+', 1, level)) token
  5     from test
  6     connect by level <= regexp_count(col, ',') + 1
  7    )
  8  select regexp_substr(token, '^[a-zA-Z]+') letters,
  9         regexp_substr(token, '[0-9]+$') digits
 10  from inter
 11  where regexp_like(token, '^[a-zA-Z]+[0-9]+$');

LETTERS    DIGITS
---------- ----------
ABC        1234
dEf        456

SQL>

使用 SUBSTR(以及 INSTRTRANSLATE):

SQL Fiddle

Oracle 11g R2 架构设置:

CREATE TABLE data ( value ) AS
SELECT 'ABC1234'     FROM DUAL UNION ALL
SELECT 'ABC123D'     FROM DUAL UNION ALL
SELECT 'ABC '        FROM DUAL UNION ALL
SELECT 'ABC'         FROM DUAL UNION ALL
SELECT 'DEFG456'     FROM DUAL UNION ALL
SELECT 'GHI'         FROM DUAL UNION ALL
SELECT 'JKLMNOPQRS9' FROM DUAL;

查询 1:

SELECT value,
       SUBSTR( value, 1, first_digit - 1 ) AS prefix,
       TO_NUMBER( SUBSTR( value, first_digit ) ) AS suffix
FROM   (
  SELECT value,
         INSTR(
           TRANSLATE( value, '-1234567890', ' ----------' ),
           '-',
           1
         ) AS first_digit
  FROM   data
)
WHERE  SUBSTR( value, first_digit ) IS NOT NULL
AND    TRANSLATE( SUBSTR( value, first_digit ), '-1234567890', ' ' ) IS NULL

Results:

|       VALUE |     PREFIX | SUFFIX |
|-------------|------------|--------|
|     ABC1234 |        ABC |   1234 |
|     DEFG456 |       DEFG |    456 |
| JKLMNOPQRS9 | JKLMNOPQRS |      9 |

So if the value is "ABC1234" then I need to cut out ABC and 1234 seperated. But if there is only "ABC" as a value, I just need the "ABC".

在其他解决方案中,我提出一种解决方案,如下所示:

逻辑:

1) Replace all the digits to 1. Check the position of the digit occurring in the string. If there is no digit in the string then use the String.

2) Extract the alphabets from 1st position to the position where digit starts.

3) Extract the digit from the position it starts till end. If digit doesnot exists the set it NULL

  --Dataset Preparation
    with test (col) as
      (select 'ABC1234' from dual union all
       select 'ABC'     from dual union all
       select 'dEfH456'  from dual union all
       select '123GHI'  from dual union all
       select '456'     from dual
      )
     --Query
    select col Original_Column, 
           CASE 
              WHEN (instr(regexp_replace(col,'[0-9]','1'),'1',1)) = 0
           then col
           else
           substr( col,1,instr(regexp_replace(col,'[0-9]','1'),'1',1)-1) 
           end Col_Alp,

           CASE 
              WHEN (instr(regexp_replace(col,'[0-9]','1'),'1',1)) = 0
            then NULL
            Else
            substr( col,instr(regexp_replace(col,'[0-9]','1'),'1',1)) 
            END col_digit    
   from test
   where regexp_like(col, '^[a-zA-Z0-9]+$');

结果:

SQL> /
Original_Column Col_Alp col_digit
----------      -----   -----
ABC1234      ABC       1234
ABC          ABC       NULL
dEfH456      dEfH      456
123GHI       NULL       123GHI
456          NULL       456

针对提到的场景尝试下面的查询,如果字符后跟数字,我没有拆分:

with test (col) as
  (select 'ABC1234' from dual union all
   select 'ABC'     from dual union all
   select 'dEfH456'  from dual union all
   select '123GHI'  from dual union all
   select '456'     from dual
  )

  select col,reverse(trim(regexp_replace(reverse(col),'^[0-9]+',' '))) string ,trim(regexp_replace(col,'^[a-zA-Z]+',' ')) numbers from test

如果想将该字符和字符串移动到我的 case 语句的任何地方

with test (col) as
  (select 'ABC1234' from dual union all
   select 'ABC'     from dual union all
   select 'dEfH456'  from dual union all
   select '123GHI'  from dual union all
   select '456'     from dual
  )

  select v.col,case when v.string=v.numbers THEN NULL ELSE string end string , v.numbers
  from (select col,reverse(trim(regexp_replace(reverse(col),'^[0-9]+',' '))) string ,trim(regexp_replace(col,'^[a-zA-Z]+',' ')) numbers from test) v