2

我试图在 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 子句的模式。

您可以提供的任何帮助将不胜感激。

4

6 回答 6

5

笨重,但也许:

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

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

编辑:合并@Hobo 的 xlnt 建议来翻译子字符串,而不是采用翻译字符串的子字符串......

于 2009-09-30T18:11:14.010 回答
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():例如。其中上(substr(c1,1,1))在...

表现

我用 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
/
于 2009-10-01T07:04:18.580 回答
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 更好。

于 2009-09-30T18:11:29.133 回答
1

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

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

这个包叫做owa_pattern,我能找到的唯一一个9i链接就是这个

我从未使用过它,并且仍在尝试掌握正则表达式,因此无法告诉您它是否符合您的目的,但认为它可能有用。

于 2009-09-30T20:27:58.853 回答
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')

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

于 2009-10-01T20:11:51.780 回答
0

我认为您想使用 REGEXP_LIKE 而不是喜欢。

WHERE REGEXP_LIKE(fieldName, '[AZ]{2}[1-4]?.+','i');

于 2009-09-30T17:49:19.303 回答