2012-02-07 88 views
1

我有一列存儲4個字符或更少的通配符(例如????,',0??1等)。對於像0??1這樣的每一個這樣的字符串,我必須插入另一個表中的值0001到0991;對於字符串??01,值將爲0001到9901;對於字符串????,值將爲0000至9999,依此類推。如何使用字符串函數在PL/SQL中使用通配符來擴展字符串

我該如何使用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; 
/

回答

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; 
/

這裏假設你有一個帶柱rule稱爲some_table表,其中包含文本,如??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行,所有匹配所有三個給出的模式的數量。

+0

真棒!它完美地解決了我的問題。感謝您的回覆,否則我會遇到困難的時間處理instring和substring :) – Arcs 2012-02-08 16:22:49

+0

還有一件事我想問。 'some_table'有1000萬條記錄。假設每條記錄得到擴展,我將有大量記錄插入到some_other_table。我擔心這樣的程序的表現。有沒有有效的方法來處理這個問題? – Arcs 2012-02-10 13:45:32

+0

@Arcs:如果你關心這種方法的性能,用1000個記錄對它進行測試,然後在10000或100000條記錄上測試它,或者甚至更多。我還沒有對這個功能進行任何性能測試,所以我不知道它的性能如何。如果你在'some_table'中有1000萬行,每個行可以產生100行,你就有10億行。插入10億行總是需要很長時間,不管你如何插入它們。 – 2012-02-10 20:29:26

2

*替換爲%,?並_和使用LIKE子句與結果值。

+0

它將如何提供幫助?請解釋。對於'????'我在做這樣的事情:declare v_rule varchar2(50):='???? 52132'; v_cc varchar2(50); v_nat varchar2(50); v_wild number; n數; 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; 結束; – Arcs 2012-02-07 11:11:49

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; 
/
相關問題