RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1350172
Accepted
максим ильин
максим ильин
Asked:2022-04-16 00:01:00 +0000 UTC2022-04-16 00:01:00 +0000 UTC 2022-04-16 00:01:00 +0000 UTC

从字符串中选择一个或多个唯一的数字序列

  • 772
declare
p_dbs varchar(1000):='MK~RU_AR~ZEN~ADFORM_CP~3301071970_CI~FY22QO_OB~1X1_TS~APV-123895_VV~NONE_PI~123895_ID~GLD0009ADF__CV~PPV-123895_FF~CPM';
type values_t is table of varchar(150);
    t_values     values_t := values_t();
    l_char                  varchar2(1 char);
    l_buffer                varchar2(150 char);
    l_sp    boolean :=false;
    l_ep    boolean :=false;
begin
    for i in 1..length(p_dbs)
    loop
        l_char := substr(p_dbs, i, 1);
        if nvl(length(replace(translate(l_char, '0123456789', rpad(chr(1), 10, chr(1))), chr(1))), 0) = 0 and l_sp=false  and l_ep=false
        then -- char is number
            l_buffer := l_buffer || l_char;
            l_sp := true;
            end if;
        
        if nvl(length(replace(translate(l_char, '0123456789', rpad(chr(1), 10, chr(1))), chr(1))), 0) = 0 and l_sp=true  and l_ep=false 
        then l_buffer := l_buffer || l_char;
        end if;
        
        if nvl(length(replace(translate(l_char, '0123456789', rpad(chr(1), 10, chr(1))), chr(1))), 0) > 0 and l_sp=true  and l_ep=false
        then 
             if --length(l_buffer)=5 or length(l_buffer)=6
              not l_buffer  MEMBER OF t_values then 
             t_values.EXTEND;
                 t_values(t_values.COUNT) := l_buffer;
                 dbms_output.put_line(l_buffer);
                 l_buffer := '';
                 l_sp := false;
                 l_ep := true;
           end if;
        end if;
        
        if nvl(length(replace(translate(l_char, '0123456789', rpad(chr(1), 10, chr(1))), chr(1))), 0) = 0 and l_sp=false  and l_ep=true 
        then 
            l_buffer := l_buffer || l_char;
            l_sp := true;
            l_ep := false;
        end if;
        end loop;
end;

无法理解的行为,显示的值不是 1123895:

33301071970
22
1
1123895
123895
0009

如果您删除对成员的检查,它会显示正确的数据:

33301071970
22
1
1
123895
123895
0009
123895

如果检查字符数,则结果集为空。

如何实现这样的结果,即只有一个值会写入类型:

123895
oracle
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    default locale
    2022-04-17T20:55:33Z2022-04-17T20:55:33Z

    l_sp我不太明白代码中的标志 (和)应该是什么意思l_ep,因此不太明白如何修复它。

    您可以基于正则表达式构建查询。

    例如,这是一个这样的查询,它从字符串中提取数字序列:

    select regexp_substr(p_dbs, '[[:digit:]]+', 1, level) 
      from dual
    connect by regexp_substr(p_dbs, '[[:digit:]]+', 1, level) is not null
    

    工作原理:该函数REGEXP_SUBSTR返回字符串中与正则表达式匹配的第 N 个序列。正则表达式[[:digit:]]+提取数字序列。递归查询 ( connect by) 将依次提取所有数字序列,直到它们用完(将返回一个空字符串,即null)。

    现在您可以从字符串中提取所需长度的唯一序列:

    select t.numbers
      from (select regexp_substr(p_dbs, '[[:digit:]]+', 1, level) as numbers,
                   level as l --Номер последовательности с начала строки
              from dual
            connect by regexp_substr(p_dbs, '[[:digit:]]+', 1, level) is not null) t
     where length(t.numbers) in (5, 6) --фильтр по длине
     group by t.numbers
     order by min(t.l) --Сортируем последовательности в оригинальном порядке (если это нужно) 
                       -- Если сортировка не нужна, то можно обойтись DISTINCT
                       -- (убрать GROUP BY и поле L из вложенного запроса)
    

    你可以把它们拿出来:

      for r in (select t.numbers
                  from (select regexp_substr(p_dbs, '[[:digit:]]+', 1, level) as numbers,
                               level as l
                          from dual
                        connect by regexp_substr(p_dbs, '[[:digit:]]+', 1, level) is not null) t
                 where length(t.numbers) in (5, 6)
                 group by t.numbers
                 order by min(t.l)) loop
        dbms_output.put_line(r.numbers);
      end loop;
    

    可采集:

    select t.numbers bulk collect
      into t_values
      from (select regexp_substr(p_dbs, '[[:digit:]]+', 1, level) as numbers,
                   level as l
              from dual
            connect by regexp_substr(p_dbs, '[[:digit:]]+', 1, level) is not null) t
     where length(t.numbers) in (5, 6)
     group by t.numbers
     order by min(t.l);
    

    添加到原始代码

    我已经通过 regexp_substr 构造对双连接进行了测试,与当前版本相比,它需要很长时间。l_sp 数字序列的开始, l_ep 数字序列的结束

    我试图简化原始代码。看起来你可以不用标志。试试这个例子:

    declare
      p_dbs varchar(1000) := 'MK~RU_AR~ZEN~ADFORM_CP~3301071970_CI~FY22QO_OB~1X1_TS~APV-123895_VV~NONE_PI~123895_ID~GLD0009ADF__CV~PPV-123895_FF~CPM';
      type values_t is table of varchar(150);
      t_values values_t := values_t();
      l_char   varchar2(1 char);
      l_buffer varchar2(150 char);
    begin
      for i in 1 .. length(p_dbs) loop
        l_char := substr(p_dbs, i, 1);
        --Проверка на цифру
        if length(trim(translate(l_char, '01234576789', ' '))) is null then
          -- Если цифра, добавляем ее в последовательность
          l_buffer := l_buffer || l_char;
        elsif l_buffer is not null then
          --Если не цифра, то проверяем есть ли последовательность
          --Выполняем все нужные проверки
          if length(l_buffer) in (5, 6) and not l_buffer MEMBER OF t_values then
            t_values.EXTEND;
            t_values(t_values.COUNT) := l_buffer;
            dbms_output.put_line(l_buffer);
          end if;
          l_buffer := '';
        end if;
      
      end loop;
      --Проверка на случай если числовая последовательность в самом конце строки
      if l_buffer is not null then
        if (length(l_buffer) = 5 or length(l_buffer) = 6) and not l_buffer
         MEMBER OF t_values then
          t_values.EXTEND;
          t_values(t_values.COUNT) := l_buffer;
          dbms_output.put_line(l_buffer);
        end if;
        l_buffer := '';
      end if;
    end;
    

    因此,该函数可能如下所示:

    create or replace function get_distinct_dbs_2(p_dbs in varchar2)
      return varchar2 deterministic as
    
      type values_t is table of varchar(150);
      t_values values_t := values_t();
      l_ret    varchar2(4000 char);
      l_char   varchar2(1 char);
      l_buffer varchar2(35 char);
    begin
      for i in 1 .. length(p_dbs) loop
        l_char := substr(p_dbs, i, 1);
        --Проверка на цифру
        if length(trim(translate(l_char, '01234576789', ' '))) is null then
          -- Если цифра, добавляем ее в последовательность
          l_buffer := l_buffer || l_char;
        elsif l_buffer is not null then
          --Если не цифра, то проверяем есть ли последовательность
          --Выполняем все нужные проверки
          if length(l_buffer) in (5, 6) and not l_buffer MEMBER OF t_values then
            t_values.EXTEND;
            t_values(t_values.COUNT) := l_buffer;
            l_ret := l_ret || ';' || l_buffer;
          end if;
          l_buffer := '';
        end if;
      
      end loop;
      --Проверка на случай если числовая последовательность в самом конце строки
      if length(l_buffer) in (5, 6) and not l_buffer MEMBER OF t_values then
        l_ret := l_ret || ';' || l_buffer;
      end if;
    
      l_ret := ltrim(l_ret, ';');
      return l_ret;
    end;
    

    显然,在您的代码中,两个相互影响的条件存在错误:

    --Добавили цифру, начали последовательность.
    if l_test=TRUE and l_sp=false  and l_ep=false then
        l_buffer := l_buffer || l_char;
        l_sp := true;
    end if;
    --Если последовательность начата, то добавляем цифру еще раз
    if l_test=TRUE and l_sp=true  and l_ep=false then 
        l_buffer := l_buffer || l_char;
    end if;
    

    因此,该函数会将序列的第一个字符附加两次,从而导致错误。例如,对于输入字符串1235a,将返回值11235。

    • 1

相关问题

  • 哪些任务使用显式或隐式游标?

  • ORA-01017 无效的用户名/密码

  • 创建空程序时出错

  • Oracle Database 18c EX 回滚安装不解释

  • 如何知道 users 表中的 expiry_date 列是否已更改?

  • 正常在字符串中查找元字符

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5