从Oracle

时间:2017-05-17 13:55:54

标签: regex oracle

我想弄清楚可以在SQL查询中提取表之间的连接条件子句的模式,假设ANSI表示法正在使用中。

例如,给定查询:

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

我知道任务并不那么容易,但是我并不打算让它完美地运作,所以在比赛中有点噪音被认为是可行的。另请注意,噪声将在后续任务中处理。

我在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 | $))代替,但这导致只有一行包含空字符串。

有什么想法吗?

2 个答案:

答案 0 :(得分: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)
 ;

答案 1 :(得分:0)

试试这个正则表达式:
(?i)(?<=join\s).*?(?=left|right|inner|where)

演示here
我不确定是否添加&#34;其中&#34;到分隔符列表是一件好事。你告诉我!

编辑:

由于不可能使用外观,我建议使用捕获组来实现:
(?i)join\s(.*?)(?:left|right|inner|where)

演示here
然后你只需扔掉比赛,你在这里感兴趣的是捕获组1。