0

ユーザーの詳細を含むデータベースがあります。「firstname」と「lastname」に別々の列はありません。「name」という 1 つの列のみを使用しました。私のクエリは次のようなものです:

ps_details=con.prepareStatement("select * from student_details where name=?");  
ps_details.setString(1,name);

問題は:

db では、名前は大文字で格納されます。そのため、ユーザーが自分の名前を小文字または大/小文字混合で入力すると、検索は失敗します。この問題の効率的な解決策は何ですか?

さらに、'name' が大文字だけでなく小文字、大文字と小文字が混在した状態で db に格納されている場合、つまり大文字と小文字の区別が事前にわからない場合はどうなるでしょうか。like句も使いたい

Oracle 11g Express Edition を使用しています。

4

3 に答える 3

3

本当に完全一致を行う場合 (つまり、ユーザーが名前の一部だけを入力するのではなく、検索を行うために名前全体を入力する必要がある場合)、式の両側をUPPERまたはLOWER関数のいずれかでラップできます。 .

SELECT *
  FROM student_details
 WHERE upper(name) = upper(?)

ただし、これを行うと、Oracle はインデックスを使用できなくなるnameため、テーブル全体をスキャンする必要があります。それは特に効率的ではありません。関数ベースのインデックスを作成することで、その問題に対処できますupper(name)

CREATE INDEX idx_upper_name
    ON student_details( upper(name) );

ただし、実際には、ワイルドカード ベースのマッチを行いたくないのではないかと思います。ほとんどの場合、ユーザーが名前の一部を入力できるようにして、その文字列を含む結果を返すようにしたいと考えています。したがって、私が学生だった場合、ユーザーが 'Justin' または 'Cave' または 'Justin Cave' または 'Just' のいずれかを検索できるようにし、これらすべての検索で私の行が返されるようにする必要があります (一致する他の行と共に、もちろん)。それをしたい場合、最も簡単な方法は、ワイルドカードLIKEと一緒に関数を使用することです%

SELECT *
  FROM student_details
 WHERE upper(name) like '%' || upper(?) || '%'

検索しているテキストのどこかに入力文字列が見つかったすべての行を返します。しかし、現実的には、パフォーマンスに関してほぼ正方形に戻ります.先頭のワイルドカードを使用すると、Oracle が で定義したインデックスを使用することから利益を得ることが非常に難しくなりますUPPER(name). これが、ほとんどの人が姓と名を別々に保存する理由です。それは彼らが何かをすることを可能にします

SELECT *
  FROM student_details
 WHERE upper(first_name) like upper(?) || '%'
    OR upper(last_name) like upper(?) || '%'

これにより、ユーザーが「Justin」、「Cave」、または「Just」を検索しても、データベース内のデータの大文字と小文字または検索に入力されたデータに関係なく、行を返すことができます。また、データに対して適切な関数ベースのインデックスを使用できます。

于 2012-06-26T17:06:41.803 に答える
2

UPPER - upper 関数は、指定された文字列内のすべての文字を大文字に変換します。変数 (ユーザー入力) とテーブル列の値の両方で使用し、比較のために両方を同じケースに変換して、両方の問題を処理します。(lower を使用することもできます - アイデアは、比較のために両方を同じケースに変換することです)。*後置ワイルドカードのみを使用して編集済み *

select * from student_details where UPPER(name) like UPPER(?) || '%'

これで遊ぶ必要がありますが、ワイルドカードを使用して次のこともできると思います。

ps_details=con.prepareStatement("select * from student_details where UPPER(name) like UPPER(?)");  
ps_details.setString(1,name%);
于 2012-06-26T16:53:16.173 に答える
1

入力で UPPER() を使用してみてください。

于 2012-06-26T16:52:45.033 に答える