如何使用字符串函数在PL / SQL中使用通配符扩展字符串

时间:2012-02-07 10:57:53

标签: sql plsql

我有一个列,它存储一个包含4个或更少野性字符的4个字符的长字符串(例如。??????01',0??1等。对于像0??1这样的每个字符串,我必须插入另一个表值0001到0991;对于字符串??01,值将为0001到9901;字符串????的值将为0000到9999,依此类推。

如何使用PL / SQL和字符串函数完成此操作?

修改

目前的代码是:

declare 

  v_rule varchar2(50) := '????52132'; 
  v_cc varchar2(50); 
  v_nat varchar2(50); 
  v_wild number; 
  n number; 

begin 

  v_cc := substr(v_rule,1,4); 
  v_nat := substr(v_rule,5); 

  dbms_output.put_line (v_cc || ' '|| v_nat); 

  if instr(v_cc, '????') <> 0 then 
    v_wild := 4; 
  end if; 

  n := power(10,v_wild); 

  for i in 0 .. n - 1 loop 
    dbms_output.put_line(substr(lpad(to_char(i),v_wild,'0' ),0,4)); 
  end loop; 

end;
/

3 个答案:

答案 0 :(得分:2)

将*替换为%,? to _并将 LIKE 子句与结果值一起使用。

答案 1 :(得分:2)

会有以下帮助吗?

BEGIN
  FOR source_row IN (SELECT rule FROM some_table)
  LOOP
    INSERT INTO some_other_table (rule_match)
      WITH numbers AS (SELECT LPAD(LEVEL - 1, 4, '0') AS num FROM DUAL CONNECT BY LEVEL <= 10000)
      SELECT num FROM numbers WHERE num LIKE REPLACE(source_row.rule, '?', '_');
  END LOOP;
END;
/

这假设您有一个名为some_table的表格,其中包含rule列,其中包含??010??1????等字词。它会在some_other_table中插入与0000到9999相匹配的所有数字,这些数字与这些野外梳理模式相匹配。

子查询

SELECT LPAD(LEVEL - 1, 4, '0') AS num FROM DUAL CONNECT BY LEVEL <= 10000)

生成00009999范围内的所有数字。然后,我们使用LIKE从此列表中过滤掉与此模式匹配的任何数字。请注意,_是使用LIKE而非?时的单字符通配符。

我使用以下数据进行设置:

CREATE TABLE some_table (rule VARCHAR2(4));

INSERT INTO some_table (rule) VALUES ('??01');
INSERT INTO some_table (rule) VALUES ('0??1');
INSERT INTO some_table (rule) VALUES ('????');
COMMIT;

CREATE TABLE some_other_table (rule_match VARCHAR2(4));

运行上面的PL / SQL块后,表some_other_table中有10200行,所有数字都与给定的三种模式相匹配。

答案 2 :(得分:1)

扩展@Oleg Dok的答案,它使用鲜为人知的事实,即下划线与%相同,但仅针对单个字符并使用PL \ SQL我认为以下是最简单的方法它。关于如何使用connect by的详细说明是here

declare

  cursor c_min_max( Crule varchar2 ) is
    select to_number(min(numb)) as min_n, to_number(max(numb)) as max_n
      from ( select '0000' as numb
               from dual
              union
             select lpad(level, 4, '0') as numb
               from dual
            connect by level <= 9999 )
     where to_char(numb) like replace(Crule, '?', '_');

  t_mm c_min_max%rowtype;

  l_rule varchar2(4) := '?091';

begin

  open c_min_max(l_rule);

  fetch c_min_max
    into t_mm;

  close c_min_max;

  for i in t_mm.min_n .. t_mm.max_n loop

    dbms_output.put_line(lpad(i, 4, '0'));

  end loop;

end;
/