2

SQL ステートメントで LIKE 句を使用して、Oracle 内の特定のパターンに一致させようとしています。

私はそのようなことをしたいと思います:

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

..しかし、これはOracle9i上にあるため、正規表現を使用できません(正規表現のサポートは10gで提供されました)。

前に 2 文字、次に 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() に適用します。どこで 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> 

2番目の方法

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

本当にregexpsを使用したい場合は、Javaストアドプロシージャとそれに付随するpl/sqlラッパーを開発できます。(Oracle9でサポートされているJavaリリースはregexpsをサポートしていると思いますが、100%確実ではありません)。そのjavaストアドプロシージャは、select文のpl/sqlラッパーを介して呼び出すことができます。

しかし、より簡単で高速です。

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 に答える
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 がインストールされていますか? この質問の理由は、顧客の 1 人が、付属のパッケージの 1 つを使用した正規表現のサポートが限られていることを指摘したためです。

パッケージはowa_patternと呼ばれ、私が見つけた唯一の9iリンクはこれです

私はそれを使用したことがなく、まだ正規表現を理解しようとしているので、目的に合うかどうかはわかりませんが、役立つかもしれないと思いました.

于 2009-09-30T20:27:58.853 に答える
0

like の代わりに REGEXP_LIKE を使用したいと思います。

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

于 2009-09-30T17:49:19.303 に答える