@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

画面からの条件指定時SQL文について

投稿者投稿内容
さかもと
ぬし
会議室デビュー日: 2004/05/14
投稿数: 586
投稿日時: 2006-04-05 13:55
お世話になります。
さかもとと申します。
(VB.net)

 業務系アプリを多く手がけるので毎回
検索画面での条件文作成で悩みます。

 『A項目とB項目は「AND」でつなげて、
B項目が入力されているときはC項目の入
力値は無視して、D項目はあいまい検索で
A項目とは「OR」でつなげて・・・。』
など、例は適当ですが、顧客によって
検索時の抽出条件はバラバラです。

 現在は昔からのソースを元として
これも例は適当ですが・・・。
コード:
If A項目 IsNot Nothing Then
     sql = sql & " HogeCd ='" & A項目 & "'"
End If

If A項目 IsNot Nothing And _
   B項目 IsNot Nothing Then
     sql = sql & " HogeName LIKE % '" & B項目 & "'%"
End If


などと文字列を条件により連結してゆきSQL文
(WHERE句)を作成していました。

 項目が少ない場合は苦にならないのですが、
増えるに従い・・・。

 今まではこの方法で乗り切ってきたのですが、
スマートなやり方を知らないだけかと思いまして
質問させて頂きました。

 良い方法をご存知の方がいらっしゃいましたら
是非教えて頂ければと思います。

 宜しくお願いいたします。


じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-04-05 14:34
引用:

さかもとさんの書き込み (2006-04-05 13:55) より:

文字列を条件により連結してゆきSQL文(WHERE句)を作成していました。


プログラムの実ソース上で書いているのですから仕方がないでしょうね。

引用:

今まではこの方法で乗り切ってきたのですが、スマートなやり方を知らないだけかと思いまして質問させて頂きました。


QueryBuilder クラスのようなものを作った記憶がありますが、
結局やっていることは何ら変わりありません。

プログラムの実ソースに書いているから気になるんでしょうけど。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
さかもと
ぬし
会議室デビュー日: 2004/05/14
投稿数: 586
投稿日時: 2006-04-05 14:47
じゃんぬねっと様、いつもお世話になります。

>プログラムの実ソースに書いているから気になるんでしょうけど。
そうなんです(笑)見た目がやはりゴリゴリしているというか・・・。
やはり仕方ないのですね・・・。

前回、あれほどがんばって書いたのに
「CSVで全件出してくれたらEXCELで勝手に使うからやっぱりいいや」
と言われて素直に「あぁそうかい」と思いました。

今日もがんばって書きます。
ありがとうございました。
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2006-04-05 14:57
私の場合、以下のような事を行っています。

ライブラリ側)
条件の種類毎のクラスを作成しておきます。(演算子毎に)
また、それを束ねる条件コレクションクラスをCollectionBaseやCollectionDictionaryを基に
作成しておきます。

テーブルアクセスクラスの抽象型を作成しておき、
条件コレクションを設定できるプロパティを公開しておきます。

アプリケーション側)
実テーブルに合わせてテーブルアクセスクラスを作成します。

画面プログラムでは条件ひとつひとつをオブジェクトとして積み上げた、
条件コレクションを事前に作成しておき、それぞれのオブジェクトに後で
入力値を設定します。
テーブルアクセスクラスの該当プロパティに設定します。
そして実際にクエリを実行するときに、条件オブジェクトに基づいた、
Where文とパラメータのコレクションを作成するようにしています。
もちろん、値が入っていない条件オブジェクトの文やパラメータは作成しないようにします。

#文章だけだと分かりづらい・・・
#説明していませんが、ネストされた条件等も実現できるようにライブラリ側で
#用意しておく必要があります。
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2006-04-05 15:07
そんな貴方に「Interpreterパターン」
#やろうとしたことはないですが…。
_________________
囚人のジレンマな日々
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2006-04-05 16:30
実ソースに書いている場合、ごちゃごちゃしてしまうのは仕方ないと思ってますが

WHERE 条件A AND 条件B AND 条件C

みたいなときに、条件Aがないときは最初のANDはいらないし、、
条件Cがないときは2番目のANDはいらないし、、面倒くさい、という悩みは私もありました。

私は各条件を配列に入れておいて(実際はArrayListに入れといてToArrayしますが)、
String.Join(" AND "array)
なんてやったりします。いらない条件は配列に入れなければいいのです。

ORがあるとまた複雑になりますが

WHERE 条件A AND 条件B OR 条件C AND 条件D

は結局

WHERE (条件A AND 条件B) OR (条件C AND 条件D)

と解釈されるので内側をつくった後にORでJoinすれば同じことです。

ただ、オブジェクト指向という観点から考えるとNAL-6295さんのようなやりかたを
見習いたいですけどね。
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2006-04-05 18:25
#参考までに…。

私の場合、
コード:

Public Function GetWhereCondition(Param As Xml.XmlNode) As String


みたいなメソッドを作って XML として抽出条件のパラメータの生成・受け渡しを行い、グルグル回して WHERE 条件を生成しています。

↓パラメータの例
コード:
<conditions combination="and">
  <condition column="organization" type="int" compare="not">1</condition>
  <conditions combination="and">
    <condition column="organization" type="int" compare=">=">3</condition>
    <condition column="organization" type="int" compare="<">6</condition>
  </conditions>
  <conditions combination="or">
    <condition column="employee" type="char">000123</condition>
    <condition column="employee" type="char">001234</condition>
    <condition column="employee" type="char">012345</condition>
  </conditions>
</conditions>



↓以下、生成されるWHERE条件
WHERE organization <> 1
AND (organization >= 3 AND organization < 6)
AND (employee ='000123' OR employee ='001234' OR employee ='012345')
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-04-05 21:32
引用:

べるさんの書き込み(2006-04-05 16:30)より:

WHERE 条件A AND 条件B AND 条件C

みたいなときに、条件Aがないときは最初のANDはいらないし、、
条件Cがないときは2番目のANDはいらないし、、面倒くさい、という悩みは私もありました。


 何でもかんでも "AND 条件" で連結して、最後に SubString(4) しています。

 OR 連結?スペースはいくら空いてもかまわないのだから、"OR 条件" …おお! HTML では連続スペースは1つに省略されるorz

〆 written by Jitta@わんくま同盟 on 2006/04/05
□ Microsoft MVP for Visual Developer ASP/ASP.NET October, 2005 - September, 2006

スキルアップ/キャリアアップ(JOB@IT)