2017-04-14 17 views
0

我下面的問題一個只讀用戶用他一個數據庫:分裂的文本與只讀權限錶行

場景:

呼叫中心的員工對公司提交的門票給我通過我們的數據庫代表我們的客戶。呼叫中心在他們的消息中包含確切長度的字母數字批號,供我排除故障。根據票證更新的次數,一張票可能有多個消息,每個消息中嵌入了零個或多個這樣的字母數字批號。我可以使用Oracle SQL和SQL工具訪問所有這些消息。

我怎樣才能提取批號,使所有給定的批號的單列表?

示例數據:

-- Accessing Ticket 1234 -- 
SELECT * 
FROM communications_detail 
WHERE ticket_num = 1234; 


-- Results -- 
TICKET_NUM | MESSAGE_NUM | MESSAGE 
------------------------------------------------------------------------------ 
     1234 |   1 | A customer recently purchased some products with 
      |    | a lot number of vwxyz12345 and wants to know if 
      |    | they have been recalled. 
------------------------------------------------------------------------------ 
     1234 |   2 | Same customer found lots vwxyz23456 and zyxwv12345 
      |    | in their storage as well and would like those checked. 
------------------------------------------------------------------------------ 
     1234 |   3 | These lots have not been recalled. Please inform 
      |    | the client. 

迄今爲止在:

我能夠隔離常量字符串用下面的代碼的批號,但是它被投入標準輸出而不是表格格式。

DECLARE 
    msg VARCHAR2(200) := 'Same customer found lots xyz23456 and zyx12345 in their storage as well and would like those checked.'; 
    cnt NUMBER  := regexp_count(msg, '[[:alnum:]]{10}'); 
BEGIN 
    IF cnt > 0 THEN 
     FOR i IN 1..cnt LOOP 
     Dbms_Output.put_line(regexp_substr(msg, '[[:alnum:]]{10}', 1, i)); 
     END LOOP; 
    END IF; 
END; 
/

目標:

  • 輸出結果轉換成一個表本身可被用作在一個更大的查詢語句的表。
  • 以某種方式能夠將此應用於與原始票證關聯的所有消息。

更新:從長,以避免與在消息中的真實字混亂8至10個字符改變了例如批號。真實世界的場景有更長的代碼和非常特定的格式,所以會使用更復雜的正則表達式。

更新2:嘗試使用表變量而不是標準輸出。它沒有錯誤,但它沒有填充我的查詢標籤...這可能只是用戶錯誤...!

DECLARE 
    TYPE lot_type IS TABLE OF VARCHAR2(10); 
    lots lot_type := lot_type(); 
    msg VARCHAR2(200) := 'Same customer found lots xyz23456 and zyx12345 in their storage as well and would like those checked.'; 
    cnt NUMBER  := regexp_count(msg, '[[:alnum:]]{10}'); 
BEGIN 
    IF cnt > 0 THEN 
     FOR i IN 1..cnt LOOP 
     lots.extend(); 
     lots(i) := regexp_substr(msg, '[[:alnum:]]{10}', 1, i); 
     END LOOP; 
    END IF; 
END; 
/
+0

你可以與流水線表函數做到這一點,但是這是一個對象,你需要在數據庫中創建,因此,如果有人不會讓你到的是,它不會工作。僅供參考,您示例中的計數返回3. – OldProgrammer

+0

您可以將需要的結果集輸出到表變量中嗎? –

+0

@OldProgrammer - 呵呵,所以它會返回3 ...這個實際情況超過了15個字符,並且更加具體,但是我會添加一個註釋。感謝您的支持! @NateAnderson - 可能,我正在調查它。我被困在如何實際添加搜索數據到表中,因爲我不能'插入'任何東西。 – Metomorphose

回答

1

這是相匹配的地段掩蓋你提供一個正則表達式格式:'[a-z]{3}[0-9]{5}'。使用這樣的東西將有助於避免您在問題中提到的誤報。

現在,這裏爲您提供一個只讀的純SQL解決方案。

with cte as ( 
     select 'Same customer found lots xyz23456 and zyx12345 in their storage as well and would like those checked.' msg 
     from dual) 
select regexp_substr(msg, '[a-z]{3}[0-9]{5}', 1, level) as lotno 
from cte 
connect by level <= regexp_count(msg, '[a-z]{3}[0-9]{5}') 
; 

我正在使用WITH子句來生成數據。重要的是使用CONNECT BY操作符,它是Oracle分層數據語法的一部分,但是這裏從一行生成一個表。僞列LEVEL允許我們遍歷字符串並挑出正則表達式模式的不同事件。

下面是輸出:

SQL> r 
    1 with cte as (select 'Same customer found lots xyz23456 and zyx12345 in their storage as well and would like those checked.' msg from dual) 
    2 select regexp_substr(msg, '[a-z]{3}[0-9]{5}', 1, level) as lotno 
    3 from cte 
    4 connect by level <= regexp_count(msg, '[a-z]{3}[0-9]{5}') 
    5* 

LOTNO 
---------- 
xyz23456 
zyx12345 

SQL> 
+0

謝謝,這很好解釋!我將在星期一再次訪問數據庫時嘗試它。 – Metomorphose

+0

需要稍作修改才能刪除奇怪的重複條目,但它起作用! – Metomorphose

+0

很高興聽到它。我確實說過你可能會驚訝於你可以用pur Oracle SQL做多少事情。 – APC