- PR -

ODP.NETでバインド変数を使用した固定長項目を条件とした時のレコード抽出

投稿者投稿内容
VIVIENNE
常連さん
会議室デビュー日: 2004/08/18
投稿数: 21
投稿日時: 2004-08-23 11:16
質問です。

ODP.NETを使用してVB.NETでプログラムを作成しているのですが、
固定長の項目を条件にした場合のレコード抽出がうまくいきません。

SQLとしては、バインド変数を使用しています。
  
SQL:"SELECT AAA FROM TABLENAME WHERE BBB = :BBB"

「BBB」の項目は固定長文字列6バイトの項目なのですが、
6バイトより短い値が入っていた場合に、
その値を条件として、抽出しようとするとうまくいきません。
(6バイトの値が入っている場合は、抽出できました。)

例:DBのBBBに"2004"が入っていて、そのレコードを抽出したい場合、
  バインド変数の「BBB」に"2004"をセットすると、抽出できない。
  DBのBBBに"200408"が入っていて、そのレコードを抽出したい場合、
  バインド変数の「BBB」に"200408"をセットすると、抽出できました。


できれば、SQL文を変更したくありません。
ワイルドカードの使用や、バインド変数を使わなければ抽出できるのですが、
それでは、SQL文の変更を行わなければならないので、
最終手段をしたいのですが、どなたか変更しなくてもできるよう、
知恵をお貸しください。

よろしくお願いいたします。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-08-23 11:32
引用:

VIVIENNEさんの書き込み (2004-08-23 11:16) より:

ODP.NETを使用してVB.NETでプログラムを作成しているのですが、
固定長の項目を条件にした場合のレコード抽出がうまくいきません。

「BBB」の項目は固定長文字列6バイトの項目なのですが、
6バイトより短い値が入っていた場合に、
その値を条件として、抽出しようとするとうまくいきません。
(6バイトの値が入っている場合は、抽出できました。)


 固定長は、その名の通り固定の長さがあります。後ろに空白(ASCIIコードで0x20)を足して、その長さにしてあげてください。

例:
String fixedLingthValue = value.PadRight(6);


ん?
引用:

例:DBのBBBに"2004"が入っていて、そのレコードを抽出したい場合、
  バインド変数の「BBB」に"2004"をセットすると、抽出できない。
  DBのBBBに"200408"が入っていて、そのレコードを抽出したい場合、
  バインド変数の「BBB」に"200408"をセットすると、抽出できました。

できれば、SQL文を変更したくありません。
ワイルドカードの使用や、バインド変数を使わなければ抽出できるのですが、
それでは、SQL文の変更を行わなければならない


 固定長だろうが、可変長だろうが、"200408"というデータを"2004"で検索したければ、SQLを変更しなければなりませんけど?(SELECT ... WHERE BBB LIKE :BBB で、:BBBにバインドする値を'2004%'とする)
例えば、

BBB
-----
200405
200406
200407
200408

というデータがあったとして、どのような入力で、どのような結果を得たいのでしょうか?

[ メッセージ編集済み 編集者: Jitta 編集日時 2004-08-23 11:39 ]
VIVIENNE
常連さん
会議室デビュー日: 2004/08/18
投稿数: 21
投稿日時: 2004-08-23 11:55
回答ありがとうございました。

早速、ご指摘の通り、空白をつめてパラメータにセットして、
抽出を行ってみましたが、残念ながら抽出できませんでした。

他に要因があるのでしょうか?
VIVIENNE
常連さん
会議室デビュー日: 2004/08/18
投稿数: 21
投稿日時: 2004-08-23 12:02
すいません。 Jitta様。
文章を最後まで読んでませんでした。

引用:
--------------------------------------------------------------------------------

固定長だろうが、可変長だろうが、"200408"というデータを"2004"で検索したければ、SQLを変更しなければなりませんけど?(SELECT ... WHERE BBB LIKE :BBB で、:BBBにバインドする値を'2004%'とする)
例えば、

BBB
-----
200405
200406
200407
200408

--------------------------------------------------------------------------------

上記についてですが、
BBB
-----
2001
2002
2003
2004

のようなデータが入っていた時に、
"2004"の条件で抽出を行いたいのです。
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2004-08-23 12:37
引用:

Jittaさんの書き込み (2004-08-23 11:32) より:
引用:

VIVIENNEさんの書き込み (2004-08-23 11:16) より:

ODP.NETを使用してVB.NETでプログラムを作成しているのですが、
固定長の項目を条件にした場合のレコード抽出がうまくいきません。

「BBB」の項目は固定長文字列6バイトの項目なのですが、
6バイトより短い値が入っていた場合に、
その値を条件として、抽出しようとするとうまくいきません。
(6バイトの値が入っている場合は、抽出できました。)


 固定長は、その名の通り固定の長さがあります。後ろに空白(ASCIIコードで0x20)を足して、その長さにしてあげてください。




固定長の場合、後ろに空白を足さなくても比較時に自動的に伸張されるはずです。
可変長の場合は、後ろに空白があるなら、それも含めて比較対象になりますが・・・。

よって、原因は他にあると考えたほうが良いかもしれません。
_________________
「伝える」とは「人に云う」と書く。
http://d.hatena.ne.jp/NAL-6295/
VIVIENNE
常連さん
会議室デビュー日: 2004/08/18
投稿数: 21
投稿日時: 2004-08-23 13:16
NAL-6295さま、回答ありがとうございます。

やはり、他の原因なのでしょうか?
そうなると、私のスキルでは、どうしようもないのかもしれません。

SQLを
 1."SELECT AAA FROM TABLENAME WHERE BBB = '2004'"
 2."SELECT AAA FROM TABLENAME WHERE BBB = '" & strBBBValue & "'"
※strBBBValueは変数で、"2004"を代入
 3."SELECT AAA FROM TABLENAME WHERE BBB LIKE :BBB"
※:BBBのパラメータに"2004%"を代入

の上記のように変更すると、抽出は可能でした。

環境が原因なのか、ODP.NETの仕様なのかわかりませんが、
現状では、打つ手なしって感じです。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-08-23 13:36
引用:

NAL-6295さんの書き込み (2004-08-23 12:37) より:

固定長の場合、後ろに空白を足さなくても比較時に自動的に伸張されるはずです。
可変長の場合は、後ろに空白があるなら、それも含めて比較対象になりますが・・・。



「Oracle9i SQLリファレンス」より:
引用:

空白埋め比較セマンティクス
2 つの値の長さが異なる場合、Oracle はまず短い方の値の最後に空白を追加して、2 つの値が同じ長さになるようにします。次に、その2 つの値を、最初に異なる文字まで1 文字ずつ比較します。最初に異なる文字の位置で、大きい方の文字を持つ値の方が大きいとみなされます。2 つの値に異なる文字がない場合、その2 つの値は等しいとみなされます。この規則では、2 つの値の後続空白数のみが異なる場合、その2 つの値は等しいとみなされます。Oracle では、比較する両方の値が、CHAR データ型、NCHARデータ型、テキスト・リテラルのいずれかの式の場合、またはUSER ファンクションの戻り値の場合のみ空白埋め比較セマンティクスを使用します。


おおっと!なるほど、うまくいかないのは、パラメータ入力の方がVARCHARと判断され、非空白埋め比較セマンティクスが使われている可能性が大ですね。
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2004-08-23 13:48
引用:

Jittaさんの書き込み (2004-08-23 13:36) より:
引用:

NAL-6295さんの書き込み (2004-08-23 12:37) より:

固定長の場合、後ろに空白を足さなくても比較時に自動的に伸張されるはずです。
可変長の場合は、後ろに空白があるなら、それも含めて比較対象になりますが・・・。



「Oracle9i SQLリファレンス」より:
引用:

空白埋め比較セマンティクス
2 つの値の長さが異なる場合、Oracle はまず短い方の値の最後に空白を追加して、2 つの値が同じ長さになるようにします。次に、その2 つの値を、最初に異なる文字まで1 文字ずつ比較します。最初に異なる文字の位置で、大きい方の文字を持つ値の方が大きいとみなされます。2 つの値に異なる文字がない場合、その2 つの値は等しいとみなされます。この規則では、2 つの値の後続空白数のみが異なる場合、その2 つの値は等しいとみなされます。Oracle では、比較する両方の値が、CHAR データ型、NCHARデータ型、テキスト・リテラルのいずれかの式の場合、またはUSER ファンクションの戻り値の場合のみ空白埋め比較セマンティクスを使用します。


おおっと!なるほど、うまくいかないのは、パラメータ入力の方がVARCHARと判断され、非空白埋め比較セマンティクスが使われている可能性が大ですね。



ってことは、パラメータのインスタンスを生成する時に適切な型を明示してあげるべきって事でしょうかね。
_________________
「伝える」とは「人に云う」と書く。
http://d.hatena.ne.jp/NAL-6295/

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