- - PR -
Javaでの実行結果とSQL+の実行結果が異なる
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2005-04-13 19:05
藤江と申します。
現在、下記のような現象が起き悩んでいます。 Javaを実行すると、対象レコードに更新はかかっているのですが、 副問合せ部分が正常に取得できず、NULLがセットされてしまいます。 しかし、このような現象になるパターンも掴めておらず、 全てがこのようになるとは限りません。 正常に更新される場合の方が多いのです。 何かご存知でしたら、教えて下さい。 どうぞよろしくお願いいたします。 ■DB状態(初期状態)Oracle 9.0.1 DB_A --------------------------------- CD | KINGAKU | UPDATE_USER --------------------------------- 01 | 0 | system 02 | 0 | system 03 | 1500 | system --------------------------------- DB_B --------------------------------------- CD | YM | KINGAKU | UPDATE_USER --------------------------------------- 01 | 200503 | 1000 | system 01 | 200504 | 500 | system 01 | 200505 | 1000 | system 02 | 200504 | 1000 | system 02 | 200505 | 1000 | system 03 | 200504 | 1500 | system --------------------------------------- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ■Javaソース(JDBC)と実行結果 PreparedStatement ps = null; int para = 1; String sql = " update DB_A a " + " set KINGAKU = (select sum(b.KINGAKU) " + " from DB_B b " + " where b.CD = a.CDE " + " and b.YM = a.YM ) " + " UPDATE_USER = ? " + " where (a.CD = ? and " + " a.YM = ? ) " + " or (a.CD = ? and " + " a.YM = ? ) " ; ps = conn.prepareStatement(sql); ps.setString (para++, "FUJIE"); ps.setString (para++, "01"); ps.setString (para++, "200503"); ps.setString (para++, "01"); ps.setString (para++, "200504"); ps.executeUpdate(); DB_A --------------------------------- CD | KINGAKU | UPDATE_USER --------------------------------- 01 | <NULL> | FUJIE ← このレコードに対して更新はかかっていいますが、KINGAKUにNULLがセットされます。 02 | 0 | system 03 | 1500 | system --------------------------------- DB_B --------------------------------------- CD | YM | KINGAKU | UPDATE_USER --------------------------------------- 01 | 200503 | 1000 | system 01 | 200504 | 500 | system 01 | 200505 | 1000 | system 02 | 200504 | 1000 | system 02 | 200505 | 1000 | system 03 | 200504 | 1500 | system --------------------------------------- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ■SQL+での実行結果 update DB_A a set KINGAKU = (select sum(b.KINGAKU) from DB_B b where b.CD = a.CDE and b.YM = a.YM ) UPDATE_USER = 'FUJIE' where (a.CD = '01' and a.YM = '200503' ) or (a.CD = '01' and a.YM = '200504' ) ; DB_A --------------------------------- CD | KINGAKU | UPDATE_USER --------------------------------- 01 | 1500 | FUJIE ← 正常に更新されています。 02 | 0 | system 03 | 1500 | system --------------------------------- DB_B --------------------------------------- CD | YM | KINGAKU | UPDATE_USER --------------------------------------- 01 | 200503 | 1000 | system 01 | 200504 | 500 | system 01 | 200505 | 1000 | system 02 | 200504 | 1000 | system 02 | 200505 | 1000 | system 03 | 200504 | 1500 | system --------------------------------------- | ||||
|
投稿日時: 2005-04-13 19:24
DB_AにYMってカラムはあるんですよね? あったとして合計値が1500になりますか?
SETの各要素間ってカンマ区切りだと思うのですが、スペース区切りで動くんでしたっけ? | ||||
|
投稿日時: 2005-04-13 19:31
お返事を頂きありがとうございます。 ソースを転記したときにカンマを落としてしまったようです。 大変申し訳ございません。 実際のソースにはカンマがあります。 update DB_A a set KINGAKU = (select sum(b.KINGAKU) from DB_B b where b.CD = a.CDE and b.YM = a.YM ) , ← ここにカンマがあります。 UPDATE_USER = 'FUJIE' where (a.CD = '01' and a.YM = '200503' ) or (a.CD = '01' and a.YM = '200504' ) ; どうぞよろしくお願い致します。 | ||||
|
投稿日時: 2005-04-13 19:39
いや、それはそれでいいんですが、肝心の疑問のほうにお答えいただいていないです。 DB_AとDB_BのCDとYMが一致する条件であれば、1000や500が合計値になりそうなんですが、 テーブルの構成やSQLは本当にあっていますか? | ||||
|
投稿日時: 2005-04-13 19:40
色々な個所で辻褄が合わなくなってしまい、申し訳ございません。 再度、記述し直しましたので、どうぞよろしくお願い致します。 uk様、ご指摘頂きまして、どうもありがとうございました。 ■DB状態(初期状態)Oracle 9.0.1 DB_A --------------------------------- CD | YM | KINGAKU | UPDATE_USER --------------------------------- 01 |200503| 0 | system 01 |200504| 0 | system 02 |200503| 0 | system 03 |200503| 1500 | system --------------------------------- DB_B --------------------------------------- CD | YM | KINGAKU | UPDATE_USER --------------------------------------- 01 | 200503 | 1000 | system 01 | 200503 | 500 | system 01 | 200504 | 1000 | system 02 | 200504 | 1000 | system 02 | 200505 | 1000 | system 03 | 200504 | 1500 | system --------------------------------------- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ■Javaソース(JDBC)と実行結果 PreparedStatement ps = null; int para = 1; String sql = " update DB_A a " + " set KINGAKU = (select sum(b.KINGAKU) " + " from DB_B b " + " where b.CD = a.CDE " + " and b.YM = a.YM ) , " + " UPDATE_USER = ? " + " where (a.CD = ? and " + " a.YM = ? ) " + " or (a.CD = ? and " + " a.YM = ? ) " ; ps = conn.prepareStatement(sql); ps.setString (para++, "FUJIE"); ps.setString (para++, "01"); ps.setString (para++, "200503"); ps.setString (para++, "01"); ps.setString (para++, "200504"); ps.executeUpdate(); DB_A --------------------------------- CD | YM | KINGAKU | UPDATE_USER --------------------------------- 01 |200503| <NULL> | FUJIE ← このレコードに対して更新はかかっていいますが、KINGAKUにNULLがセットされます。 01 |200504| 1000 | FUJIE ← 正常に更新されています。 02 |200503| 0 | system 03 |200503| 1500 | system --------------------------------- DB_B --------------------------------------- CD | YM | KINGAKU | UPDATE_USER --------------------------------------- 01 | 200503 | 1000 | system 01 | 200503 | 500 | system 01 | 200504 | 1000 | system 02 | 200504 | 1000 | system 02 | 200505 | 1000 | system 03 | 200504 | 1500 | system --------------------------------------- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ■SQL+での実行結果 update DB_A a set KINGAKU = (select sum(b.KINGAKU) from DB_B b where b.CD = a.CDE and b.YM = a.YM ) , UPDATE_USER = 'FUJIE' where (a.CD = '01' and a.YM = '200503' ) or (a.CD = '01' and a.YM = '200504' ) ; DB_A --------------------------------- CD | YM | KINGAKU | UPDATE_USER --------------------------------- 01 |200503| 1500 | FUJIE ← 正常に更新されています。 01 |200504| 1000 | FUJIE ← 正常に更新されています。 02 |200503| 0 | system 03 |200503| 1500 | system --------------------------------- DB_B --------------------------------------- CD | YM | KINGAKU | UPDATE_USER --------------------------------------- 01 | 200503 | 1000 | system 01 | 200503 | 500 | system 01 | 200504 | 1000 | system 02 | 200504 | 1000 | system 02 | 200505 | 1000 | system 03 | 200504 | 1500 | system --------------------------------------- [ メッセージ編集済み 編集者: fujie 編集日時 2005-04-13 19:42 ] | ||||
|
投稿日時: 2005-04-13 20:20
少なくともSQLには問題ないようですね。
再現性がない、とのことですがまったく同じSQLで同じパラメータでも問題が出たり出なかったり するのでしょうか。 まったくのあてずっぽうですが、コネクションやステートメントの使い回しとかしていませんか? それからSQLの構文を見て思ったのですが、実際のプログラムではSQLを動的に組み立てていたり しないでしょうか。 | ||||
|
投稿日時: 2005-04-18 19:37
お返事を頂き、ありがとうございます。
再現性については、同じSQLで同じパラメータでも、問題が出る場合と出ない場合が あります・・・。 ただ、関係無いかもしれませんが、実行毎に、原因を探るため、 INDEXを変えてみたり、不正に更新されたデータを元の状態に戻すために データのインポートをしました。 ステートメントは使い回しをしていませんが、コネクションは使い回しています。 1つのトランザクション内で使い回し、正常に終われば、コミットしています。 もしかすると、これが問題なのでしょうか。 また、実際のSQLは、指摘される通り、動的に組み立てています。 出来上がったSQLをSQL+で実行し、その結果と比べて、結果が違うと 判断しました。 これも、問題となるのでしょうか。 | ||||
|
投稿日時: 2005-04-18 20:07
で、少し気になったのですが、集計関数の結果がNULLになるのは 対象行がなかったか、取得した集計対象のデータがすべてNULLの場合に なると思うのですが・・・ 実行時にキーを更新しているとか、データのインポートを実行していたって いう状態ではなく、まったく他のどのプロセスも更新しない状態で実行しても 再現することがあるのでしょうか? また発生するときとしないときで状況や、動かし方などに差があったりしますか? |