模式匹配与喜欢的条款

时间:2009-09-30 17:45:41

标签: sql oracle plsql oracle9i

我试图在SQL语句中使用LIKE子句来匹配Oracle中的某个模式。

我想这样做:

LIKE '[A-Z][A-Z][1-4]%'

..但是我不能使用正则表达式,因为这是在Oracle9i (正则表达式支持10g)。

我试图匹配之前有两个字符的东西,然后是1到4之间的数字,以及除此之外的任何东西。我试过这个,但它似乎没有用。我能够让它发挥作用的唯一方法是:

WHERE ...
LIKE '%1__' OR 
LIKE '%2__' OR 
LIKE '%3__' OR 
LIKE '%4__'

我不确定我想要这样做的方式是否可行或者是正确的方式,因为我从未尝试过使用LIKE子句的模式。

非常感谢您给予的任何帮助。

6 个答案:

答案 0 :(得分:5)

笨蛋,但也许:

select *
  from <your_table>
 where TRANSLATE(SUBSTR(<blah>,1,3),'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234',
                                    'AAAAAAAAAAAAAAAAAAAAAAAAAA1111') = 'AA1';

可能适合您的需求....

编辑:@Lobo的xlnt建议翻译子字符串,而不是取翻译字符串的子字符串...

答案 1 :(得分:3)

试试这个:

SELECT c1
FROM   t1
WHERE  substr(c1,1,1) IN ('A','B','C','D',
                          'E','F','G','H',
                          'I','J','K','L',
                          'M','N','O','P',
                          'Q','R','S','T',
                          'U','V','W','X',
                          'Y','Z')
       AND substr(c1,2,1) IN ('A','B','C','D',
                              'E','F','G','H',
                              'I','J','K','L',
                              'M','N','O','P',
                              'Q','R','S','T',
                              'U','V','W','X',
                              'Y','Z')
       AND substr(c1,3,1) IN ('1','2','3','4')
/

如果你还想匹配较低的字母,那么将upper()函数应用于2第一个substr(): 例如。其中upper(substr(c1,1,1))in ...

<强>性能

我用regexp_like和没有测试查询的性能。正如您所看到的,没有regexp_like函数的查询速度提高了100%。 (注意:两个查询都进行了软解析)

SQL> select count(*) from t1;                                                                                                                     

  COUNT(*)
----------
    458752

Elapsed: 00:00:00.02
SQL> set timing off;                                                                                                                                  
SQL> select count(*) from t1;                                                                                                                     

  COUNT(*)
----------
    458752

SQL> set timing on;                                                                                                                                   
SQL> select count(*) from t1 where regexp_like(c1, '[A-Z][A-Z][1-4].*');                                                                       

  COUNT(*)
----------
     65536

Elapsed: 00:00:02.66
SELECT count(*)
FROM   t1
WHERE  substr(c1,1,1) IN ('A','B','C','D',
                          'E','F','G','H',
                          'I','J','K','L',
                          'M','N','O','P',
                          'Q','R','S','T',
                          'U','V','W','X',
                          'Y','Z')
       AND substr(c1,2,1) IN ('A','B','C','D',
                              'E','F','G','H',
                              'I','J','K','L',
                              'M','N','O','P',
                              'Q','R','S','T',
                              'U','V','W','X',
                              'Y','Z')
       AND substr(c1,3,1) IN ('1','2','3','4')
 18  /                                                                                                                                                

  COUNT(*)
----------
     65536

Elapsed: 00:00:01.15
SQL> 

第二种方法

获取A,Z,1和4的ascii值

SQL> select ascii('A') from dual;                                                                                                                     

ASCII('A')
----------
        65


SQL> select ascii('Z') from dual;                                                                                                                     

ASCII('Z')
----------
        90


SQL> select ascii('1') from dual;                                                                                                                     

ASCII('1')
----------
        49

SQL> select ascii('4') from dual;                                                                                                                     

ASCII('4')
----------
        52

现在您可以将您的陈述写得更短

SELECT count(* )
FROM   t1
WHERE  ascii(substr(c1,1,1)) BETWEEN 65 AND 90
       AND ascii(substr(c1,2,1)) BETWEEN 65 AND 90
       AND ascii(substr(c1,3,1)) BETWEEN 49 AND 52
/

答案 2 :(得分:1)

我建议使用INSTR

INSTR(t.column, '1', 3, 1) > 0 OR 
INSTR(t.column, '2', 3, 1) > 0 OR
INSTR(t.column, '3', 3, 1) > 0 OR
INSTR(t.column, '4', 3, 1) > 0

在LIKE中使用通配符的问题是无法控制1/2/3/4 / etc的列值在哪里 - 它可能在最后。

DCookie是对的 - 如果那个地方有数字数据,这个答案不会有办法处理。但它仍然比使用带有通配符的LIKE更好。

答案 3 :(得分:1)

总外卡,但无论如何都会建议。

您的9i数据库安装是否安装了PL / SQL Web Toolkit?问的原因是我们的一位客户指出使用随附的随附软件包提供的正则表达式支持有限。

该软件包名为owa_pattern,我能找到的唯一9i链接是one

我从来没有使用它,我仍然试图掌握正则表达式,所以不能告诉你它是否符合你的目的,但认为它可能有用。

答案 4 :(得分:1)

如果你真的想使用reg exps,你可以开发一个java存储过程和一个附带的pl / sql包装器。 (我假设Oracle 9支持的Java版本支持reg exps,我不是100%肯定)。您可以通过select语句中的pl / sql包装器调用该java存储过程。

但更简单,更快捷:

SELECT c1
FROM   t1
WHERE  substr(c1,1,1) between  'A' and 'Z'
AND    substr(c1,2,1) between  'A' and 'Z'
AND    substr(c1,3,1) IN ('1','2','3','4')

zürigschnäzlets解决方案的变体,不使用ascci函数。

答案 5 :(得分:0)

我认为你想使用REGEXP_LIKE而不是像。

WHERE REGEXP_LIKE(fieldName,'[A-Z] {2} [1-4]?。+','i');