C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: SQL 空白でないもの


(過去ログ 103 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■61509 / inTopicNo.1)  SQL 空白でないもの
  
□投稿者/ 介平 (1回)-(2011/08/17(Wed) 19:06:52)

分類:[.NET 全般] 

御世話になります。

VS2008でプログラムの勉強をしているものですが、詰まってしまい作業がすすんでいません。

どなたかご教授願います。

(仮)フォーム上には、検索条件としてID_NOとnameを入力するテキストボックスがあります。(実際にはまだ10種類ほどあります)

次にSQLが以下になります。

(仮)
SELECT * FROM T_TEST WHERE ID_NO = '"& id.text &"' and name = '"& kananame.text &"'

このSQLだとT_TESTからID_NOがid、nameがkananameと一致するレコードが抽出されると思うのですが

idとkananameは常に入力されるわけではなく、ID_NOだけの検索であったりnameだけの検索であったりします。

しかし、テーブルのID_NOとnameはかならずデータが入る仕様となります。

このままだとどちらかが空白だった場合、抽出結果が0件になってしまいます。

要はIS NOT NULL を使わずに検索条件が入力されていない方には、空白ではないという条件にするために

id.text もしくは kananame.textに何をいれて上げれば良いかお解りになる方いらっしゃいますでしょうか。

何卒宜しくお願いします。

引用返信 編集キー/
■61513 / inTopicNo.2)  Re[1]: SQL 空白でないもの
□投稿者/ 魔界の仮面弁士 (2312回)-(2011/08/17(Wed) 21:07:23)
No61509 (介平 さん) に返信
> (仮)
> SELECT * FROM T_TEST WHERE ID_NO = '"& id.text &"' and name = '"& kananame.text &"'

このような記述は避けましょう。代わりに、パラメータクエリの利用を検討してください。
(SQL 中でパラメータを使う方法は、利用するデータベース製品によって異なります)

# SQL Injection の事は理解した上で、掲示板投稿の為に
# 省略表記しただけであれば良いのですけれども。

提示されたコードだと、たとえば kananame に「@' or '@' = '@」と入力された場合、
「SELECT * FROM T_TEST WHERE ID_NO = '123' and name = '@' or '@' = '@'」
という SQL が生成され、その結果、全データが抽出されかねません。

http://technet.microsoft.com/ja-jp/library/dd362952.aspx


> idとkananameは常に入力されるわけではなく、ID_NOだけの検索であったりnameだけの検索であったりします。
> しかし、テーブルのID_NOとnameはかならずデータが入る仕様となります。
> このままだとどちらかが空白だった場合、抽出結果が0件になってしまいます。

SQL を直接生成して良いなら、たとえばこんな感じにするのは如何でしょう。

 Dim filter As New List(Of String)()
 If id.TextLength > 0 Then
  filter.Add(String.Format("ID_NO = '{0}'", id.Text.Replace("'", "''") ))
 End If
 If kananame.TextLength > 0 Then
  filter.Add(String.Format("name = '{0}'", kananame.Text.Replace("'", "''") ))
 End If
  '   :
  '   :同様にして、その他の AND 条件を列挙
  '   :
 SQL = "SELECT * FROM T_TEST"
 If filter.Count > 0 Then
  SQL &= " WHERE " & String.Join(" AND ", filter.ToArray())
 End If



SQL 文は固定的にしたいなら、それぞれの値(列ではなく、入力値の方)が空かどうかを判定してみてください。
たとえば、SQL Server でパラメータクエリを使うのであれば、

 WHERE (ID_NO = :id OR :id IS NULL) and (name = :kananame OR :kananame IS NULL)

のような感じです。名前付きパラメータを使えない処理(System.Data.OleDb + Jet Provider 等)や、
空文字列と NULL を区別しない処理系(Oracle 等)の場合は、若干手を加える必要がありますが。


> どなたかご教授願います。
http://www.tt.rim.or.jp/~rudyard/torii009.html

引用返信 編集キー/
■61514 / inTopicNo.3)  Re[1]: SQL 空白でないもの
□投稿者/ shu (940回)-(2011/08/18(Thu) 07:42:57)
No61509 (介平 さん) に返信

今回の話とちょっとはずれますが
ID_NOがPrimaryKeyなら
idが入力されているときはID_NOだけでデータを抽出して、
その他の項目はローカルで判定することによりパフォーマンスアップをすることが出来ます。

idが実際に入力されることが少ないということであれば、よく使われる組み合わせでDBアクセスし
ローカルで残りの条件を判断すると良いと思います。このときDBにアクセスする条件項目には
インデックスを作っておくと良いかと思います。
引用返信 編集キー/
■61565 / inTopicNo.4)  Re[2]: SQL 空白でないもの
□投稿者/ 介平 (2回)-(2011/08/19(Fri) 19:14:05)
返信が遅くなり申し訳御座いません。

魔界の仮面弁士様
御回答ありがとうございます。

>>SQL を直接生成して良いなら、たとえばこんな感じにするのは如何でしょう。
>>
>> Dim filter As New List(Of String)()
>> If id.TextLength > 0 Then
>>  filter.Add(String.Format("ID_NO = '{0}'", id.Text.Replace("'", "''") ))
>> End If
>> If kananame.TextLength > 0 Then
>>  filter.Add(String.Format("name = '{0}'", kananame.Text.Replace("'", "''") ))
>> End If
>> ' :
>> ' :同様にして、その他の AND 条件を列挙
>> ' :
>> SQL = "SELECT * FROM T_TEST"
>> If filter.Count > 0 Then
>>  SQL &= " WHERE " & String.Join(" AND ", filter.ToArray())
>> End If

只今こちらの方法を使わせていただいております。
実行時に「オブジェクト参照がオブジェクトインスタンスに設定されていません。」というエラーが帰ってきて
しまいます。恐らく filter がNULLだからだと思うのですが現在エラー解消に向けて奮闘しております。
回避方法などあれば教えてください。

shu様
御回答ありがとうございます。
パフォーマンスは非常に気にしているところなので
アドバイス頂きありがとうございます。
今回も含めこの先PGを組む際には参考にさせていただきます。
ありがとうございました。
引用返信 編集キー/
■61566 / inTopicNo.5)  Re[3]: SQL 空白でないもの
□投稿者/ ちくわ (1回)-(2011/08/19(Fri) 19:56:12)
> 只今こちらの方法を使わせていただいております。
> 実行時に「オブジェクト参照がオブジェクトインスタンスに設定されていません。」というエラーが帰ってきて
> しまいます。恐らく filter がNULLだからだと思うのですが現在エラー解消に向けて奮闘しております。
> 回避方法などあれば教えてください。

魔界仮面さまのコードを流用しているのであれば、filterがNothing(VBではnullという表現はしない)ではないと思います。
ステップ実行をして、どのオブジェクトがNothingかを調べた方がいいと思います。
引用返信 編集キー/
■61567 / inTopicNo.6)  Re[3]: SQL 空白でないもの
□投稿者/ 魔界の仮面弁士 (2319回)-(2011/08/19(Fri) 20:03:59)
No61565 (介平 さん) に返信
>>> Dim filter As New List(Of String)()
上記のように記述した場合には、filter 変数に List オブジェクトが
格納されますが、これを誤って
 Dim filter As List(Of String)
としていた場合は、filter 変数は Nothing となります。

この場合、filter.Add の呼び出しは失敗し、
http://msdn.microsoft.com/ja-jp/library/sxw2ez55%28VS.80%29.aspx
のエラーが発生してしまうはずです。
引用返信 編集キー/
■61568 / inTopicNo.7)  Re[3]: SQL 空白でないもの
□投稿者/ 魔界の仮面弁士 (2320回)-(2011/08/19(Fri) 20:09:22)
2011/08/19(Fri) 20:11:58 編集(投稿者)

No61565 (介平 さん) に返信
> エラーが帰ってきてしまいます。

エラーが「返」されるのは、どの行でしょうか?

たとえば、
 kananame.Text.Replace("'", "''")
の部分がエラーになるのであれば、String 値の中身が
Nothing になっていないことを確認してみてください。


TextBox.Text 自体は Nothing は返さないはずですが(長さゼロの文字列を返す)、
String 変数などを通じて strKanaName.Replace("'", "''") などと
処理している場合は、その変数(strKanaName)が Nothing の場合に
Replace メソッドが呼び出せず、NullReferenceException の例外を
発生させることになります。


> 恐らく filter がNULLだからだと思うのですが現在エラー解消に向けて奮闘しております。
> 回避方法などあれば教えてください。
エラーが発生すると、その行でコードの実行が一時的に停止すると思います。
そのときに、クイックウォッチやイミディエイト ウィンドウ、あるいはローカルウィンドウなどを使って、
どの変数が Nothing になっているのかを調べてみてください。

そうすれば、問題箇所が filter にあるのか string 変数にあるのかが
はっきりするかと思います。
引用返信 編集キー/
■61609 / inTopicNo.8)  Re[4]: SQL 空白でないもの
□投稿者/ 介平 (3回)-(2011/08/22(Mon) 18:43:18)
魔界の仮面弁士様 ちくわ様

御回答ありがとうございます。

変数宣言時にNEWを書き忘れておりました。

これによりエラーが発生していたようです。

御蔭様でエラーの解消ができました。

ありがとうございました。

また何かありましたらどうぞよろしくお願いします。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -