2017-05-17 43 views
1

我特林弄清楚,可以提取在SQL查詢表之間的連接條件子句中的模式,假定ANSI符號正在使用中。提取從SQL語句連接條件定義甲骨文

例如,假設查詢:

Select a.*, b.*, c.*, d.* 
    from a 
inner join b 
    on a.c1 = b.c1 
left outer join c on 
     c.c3 = b.c3 and b.c4 = c.c4 
    and c.c5 = b.c5 
right join d on 
    d.c9 = c.c9 
where d.c10 > 67 ; 

我想獲得:

1) b 
    on a.c1 = b.c1 
2) c on 
     c.c3 = b.c3 and b.c4 = c.c4 
    and c.c5 = b.c5 
3) d on 
    d.c9 = c.c9 

我知道這個任務並不容易,但我不換貨得到它完美地工作,所以比賽中的一些噪音被認爲是可行的。還要注意,在隨後的任務中噪音是可以治療的。

我seraching在Oracle中USER_VIEW,所以爲了使用REGEXP_ *功能,我做了一個源表進行讀操作:

create table appo_view_text (viewname varchar2(30), viewtext clob); 
insert into appo_view_text 
SELECT VIEW_NAME,to_lob(TEXT) FROM USER_VIEWS; 
commit; 

和這裏的查詢,提取什麼,我找:

with cfg as (
    select '(INNER\s+JOIN|LEFT(\s+OUTER)?\s+JOIN|RIGHT(\s+OUTER)?\s+JOIN).+?(\1|WHERE|GROUP BY|$)' pattern 
     , 'i' modifiers 
    from dual 
) 
SELECT VIEWNAME, REGEXP_SUBSTR(sourcetxt, cfg.pattern, 1, level, cfg.modifiers) aa, viewtext 
    FROM (select viewname, 
       viewtext, 
       replace(replace(viewtext,chr(13)||chr(10),' '), chr(10), ' ') sourcetxt 
       from appo_view_text 
       where viewname = 'YOUR_VIEW_NAME') --> Put here a view name 
    cross join cfg 
connect by level <= regexp_count(sourcetxt, cfg.pattern, 1, cfg.modifiers) 
; 

你會注意到正則表達式模式有一個問題,因爲它是在上面的查詢來定義:(\ 1 | $)元素將導致文本匹配一半的損失。 我嘗試使用(?:(\ 1 | $)),但是這導致只有一行包含空字符串。

有什麼想法?

+0

如果你在一個單行合併您'viewtext',那麼你就可以創建多個匹配組像'選擇(表1)內的東西/左連接上t1.col = T2(表2 .col和t2.col2 = t1.col3)內部/左連接.......其中.....'。所以'(大括號)'中的所有組都是你想要返回的那個。這聽起來像是你想要的東西嗎? – Utsav

+0

我沒有合併在表視圖文本,但我在提取查詢alredy做(見「sourcetext」欄)。這並沒有幫助,這裏 – Max

+0

這裏的主要問題是找到一個新表的開頭 – Gawil

回答

0

我覺得我得到了自己的答案:

with cfg as (
    select '(\WON\W).+?(WHERE|GROUP BY|(INNER\s+JOIN|LEFT(\s+OUTER)?\s+JOIN|RIGHT(\s+OUTER)?\s+JOIN|CROSS\s+JOIN)|$)' pattern 
     , 'i' modifiers 
    from dual 
) 
SELECT VIEWNAME, REGEXP_SUBSTR(sourcetxt, cfg.pattern, 1, level, cfg.modifiers) aa, viewtext, sourcetxt 
    FROM (select viewname, 
       viewtext, 
       replace(replace(viewtext,chr(13)||chr(10),' '), chr(10), ' ') sourcetxt 
       from appo_view_text 
       where viewname = 'VILASTAZIONE') --> Put here a view name 
    cross join cfg 
connect by level <= regexp_count(sourcetxt, cfg.pattern, 1, cfg.modifiers) 
; 
0

試試這個正則表達式:
(?i)(?<=join\s).*?(?=left|right|inner|where)

演示here
我不知道,如果加入「其中」以分隔符列表是一個很好的事情。你告訴我 !

編輯:

因爲它是不可能使用lookarounds,我建議用捕獲組做:
(?i)join\s(.*?)(?:left|right|inner|where)

演示here
那麼你就必須扔掉了比賽,你感興趣的內容這裏是捕獲組1

+0

它的工作,但Oracle不支持「東張西望」操作符(=?) – Max

+0

@Max:那好吧,我不知道,對不起......我會更新我的答案。 – Gawil