PreparedStatementでの複数検索
環境:struts1.3,postgresql8.4,JDK1.6
テキストボックスなどから1つから6つの条件でsqlを検索したいのですが
この場合、1つでもnullがある時は検索されません。
Connection con = null;
con = ProductDAO.getConnection();
//SQLの実行
String selectStatement =
"SELECT * FROM test,test_list WHERE test.id = test_list.id " +
"AND prefecture=? " +
"AND low_price>=? " +
"AND low_age>=? " +
"AND sameday_select =? " +
"AND terms_select =?" +
"AND category=?";
PreparedStatement prepStmt =
con.prepareStatement(selectStatement);
prepStmt.setString(1, aForm.getPrefecture());
prepStmt.setInt(2, aForm.getLow_price());
prepStmt.setInt(3, aForm.getLow_age());
prepStmt.setString(4, aForm.getSameday_select());
prepStmt.setString(5, aForm.getTerms_select());
prepStmt.setString(6, aForm.getCategory());
ResultSet rs = prepStmt.executeQuery();
(3) SQLの実行結果の処理
while (rs.next()) {
処理
}
この場合、if文などでaForm.getPrefecture()がnullの場合などで1つ1つ条件を付けないと駄目でしょうか?その場合、if文が膨大な数になってしまうため何か良い方法はありますか。
あるならば、具体的に教えて下さい。
No.3ベストアンサー
- 回答日時:
回答番号: No.2 の続きです。
aForm.getPrefecture() などの戻り値が null ではなく空文字 ("") の場合には、coalesce 関数の 1 つ目に渡している条件式の結果が NULL になりません。空文字の場合には NULL になるように nullif 関数をかませるとうまくいくと思います。
String selectStatement =
"SELECT * FROM test,test_list WHERE test.id = test_list.id " +
"AND coalesce(prefecture=nullif(?, ''), true) " +
"AND coalesce(low_price>=nullif(?, ''), true) " +
"AND coalesce(low_age>=nullif(?, ''), true) " +
"AND coalesce(sameday_select =nullif(?, ''), true) " +
"AND coalesce(terms_select =nullif(?, ''), true)" +
"AND coalesce(category=nullif(?, ''), true)";
値が指定されていない場合に aForm.getLow_price() などの int 型の戻り値がどうなるかが分からないのですが、0 を返すなら nullif(?, 0) などと書き換えてあげる必要があるかもしれません。
ありがとうございます。
無事if文を使わずに複数の検索ができました。
int 型もnullif(?, 0)にした場合、無事できました。
No.2
- 回答日時:
NULLに対する演算はNULLになるので、以下のSQLを書き換えてみてはいかがでしょうか。
String selectStatement =
"SELECT * FROM test,test_list WHERE test.id = test_list.id " +
"AND coalesce(prefecture=?, true) " +
"AND coalesce(low_price>=?, true) " +
"AND coalesce(low_age>=?, true) " +
"AND coalesce(sameday_select =?, true) " +
"AND coalesce(terms_select =?, true)" +
"AND coalesce(category=?, true)";
coalesce関数は引数の中から最初のNULLでない値を返すので、NULL以外が渡された場合には条件式を評価してtrueかfalseとなり、NULLが渡された場合には2つ目の引数が返されtrueとなって条件式が無視されます。
この回答への補足
回答ありがとうございます。
"AND coalesce(prefecture=?, true) " +
"AND coalesce(low_price>=?, true) " +
"AND coalesce(low_age>=?, true) " +
"AND coalesce(sameday_select =?, true) " +
"AND coalesce(terms_select =?, true)" +
"AND coalesce(category=?, true)";
上記の方法で試してみましたが、
すべての値を選択する場合は、検索できましたが、
やはりどれか一つでも値が選択されていない場合は、検索されませんでした。
logを見ると選択されていない物は、NULLではなく、="" の状態です。
No.1
- 回答日時:
if文でnull判定する以外に簡単な方法は思いつきませんね。
StringBuilder や PreparedStatement#setObject を使えば多少簡潔に出来るとは思いますが。
例 ----------------------------------------------------
StringBuilder sqlBuilder =
new StringBuilder("SELECT * FROM test,test_list WHERE test.id = test_list.id ");
List<Object> sqlParams = new ArrayList<Object>();
if (aForm.getPrefecture() != null) {
sqlBuilder.append("AND prefecture = ? ");
sqlParams.add(aForm.getPrefecture());
}
if (aForm.getLow_price() != null) {
sqlBuilder.append("AND low_price >= ? ");
sqlParams.add(aForm.getLow_price());
}
if (aForm.getLow_price() != null) {
sqlBuilder.append("AND low_age >= ? ");
sqlParams.add(aForm.getLow_age());
}
if (aForm.getSameday_select() != null) {
sqlBuilder.append("AND sameday_select = ? ");
sqlParams.add(aForm.getSameday_select());
}
if (aForm.getSameday_select() != null) {
sqlBuilder.append("AND terms_select = ? ");
sqlParams.add(aForm.getTerms_select());
}
if (aForm.getCategory() != null) {
sqlBuilder.append("AND category = ? ");
sqlParams.add(aForm.getCategory());
}
PreparedStatement prepStmt =
conn.prepareStatement(sqlBuilder.toString());
int paramIndex = 0;
for (Object param : sqlParams) {
prepStmt.setObject(++paramIndex, param);
}
ResultSet rs = prepStmt.executeQuery();
-------------------------------------------------------
(aForm の getLow_price, getLow_age はInteger型を返すとする)
この回答への補足
回答ありがとうございます。
例えば、PrefectureとSameday_selectなど複数で検索したい場合は、
さらにif文を記載するという方法ですよね。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) PHPプログラムをエクセルに張り付けると検索ボックスがでてくる! 3 2022/05/08 07:10
- PHP ここでの ②if($su_d<>"")の比較演算子 を使う理由は 1 2022/03/26 02:33
- PostgreSQL DBFluteについて質問です。 環境:PostgreSQL java8 前提:webアプリケーショ 1 2022/07/07 00:49
- MySQL 書籍の内容はまともでしょうか? 1 2023/01/22 03:07
- Access(アクセス) アクセス 有効なフィールド名、または式として認識できませんのエラー 3 2022/08/19 11:53
- PHP クエリObjectをforeachで回す時に、次のレコードへ移動せずに次のレコードを取得したい 2 2022/07/28 15:29
- PHP PHP MySql ページング 2 2022/09/20 06:38
- MySQL PhpMyAdminで作成して実行せよ。 東京23区を、皇居を中心とした4つのエリア(南東, 南西, 1 2023/06/11 11:58
- Oracle 下記のsqlで取得されるレコード以外を取得する方法ありますでしょうか。 SELECT B.番号, B 2 2022/04/20 23:21
- PHP 【PHP/MySQL】コード上で生成したクエリを基に集計クエリを作りたい 1 2022/07/28 15:06
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
テキストボックスの背景をVB...
-
PostgreSQL serial型の質問
-
timestamp が空のデータを除い...
-
Accessエクスポート時に連番を...
-
CSVファイルを読み込んでテーブ...
-
型について
-
ACCESS テキストボックスに入...
-
エクセルVBEについて
-
集まり単位?でのソート
-
フラグをたてるってどういうこ...
-
【SQL】他テーブルに含まれる値...
-
sqlに記述できない文字
-
SELECT INTOで一度に複数の変数...
-
Accessで今日から5日後
-
timestampのデータはどのように...
-
UPDATEで既存のレコードに文字...
-
オラクルのUPDATEで複数テーブル
-
エラーを起こす方法
-
テーブル名が可変の場合のクエ...
-
truncate tableを使って複数の...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CSVファイルを読み込んでテーブ...
-
テキストボックスの背景をVB...
-
timestamp が空のデータを除い...
-
SQLSERVER 連番更新について
-
エクセルVBA 10分後にエクセル...
-
SQL SERVERの BULK INSERT
-
SELECT文で足し算をした場合、N...
-
配列データに対する、要素の追...
-
ACCESS テキストボックスに入...
-
データがリストアできない!!
-
エクセルVBEについて
-
平均値のもとめ方
-
時間の比較をしたい
-
AVR studio6でeepromリードでき...
-
1つのドメインを複数のDNSで管...
-
シーケンスを使わずに主キーを...
-
date型でのbetweenについて教え...
-
Japanese schools tests
-
バッチファイルでrenを使用時、...
-
型について
おすすめ情報