使用Oracle正则表达式代替INSTR函数

时间:2016-12-28 21:20:52

标签: sql regex oracle plsql

我将数据保存在表格行上,如下所示;

t_course

+------+------------------------------------------+
| sid  |  courses                                 |
+------+------------------------------------------+
|  1   |  cs101.math102.ns202-2.phy104            |
+------+------------------------------------------+
|  2   |  cs101.math201.ens202-1.phy104-10.chm105 |
+------+------------------------------------------+
|  3   |  cs101.ns202-2.math201.ens202-1.phy104   |
+------+------------------------------------------+

现在,我想同时学习ns202和ens202所提及的课程总和。通常它应该只带来id为3的记录,它带来所有记录(因为instr)。我已经使用了很多方法,但它没有用。例如;

select count(*) from 
   t_course 
      where 
            instr(courses, 'ns202')  > 0 
        and instr(courses, 'ens202') > 0;

上面的代码没有正常工作,因为它需要ns202但是ens202本身包含ns202。

我尝试使用正则表达式,我将所有过程转换为行(拆分)但这既破坏了工作逻辑又减慢了速度。

如何根据开头的(例如ns202%)逻辑使用正则表达式而不是instr来执行此操作? (先用ns202或在点之后开始)

2 个答案:

答案 0 :(得分:2)

您可以将regexp_like与字边界结合使用,以获得同时包含ns202ens_202的行。通常,您会使用\b作为字边界。由于Oracle不支持它,替代方法是使用(\s|\W)开头^和结束$锚点。

\s - 空格字符,\W - 非单词字符。根据需要添加更多字符作为字边界。

select *
from t_course   
where regexp_like(courses,'(^|\s|\W)ns202(\s|\W|$)') 
and regexp_like(courses,'(^|\s|\W)ens202(\s|\W|$)')

答案 1 :(得分:1)

顺便说一下,ens202会遇到同样的问题 - 如果还有cens202tens202会怎样?

您可以使用正则表达式解决问题。您也可以使用LIKE运算符解决它:

select <whatever>
from   <table or tables>
where (courses like 'ns202%' or courses like '%.ns202%')
  and (courses like 'ens202%' or courses like '%.ens202%')

您可以测试这两种方法,看看哪种方法最适合您的数据。