DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Update時の未処理件数

環境/言語:[Windows2000]
分類:[.NET]

お世話になります。

やろうとしていることは、FPDから固定長ファイルを読み込み、
SQLのテーブルのKEYと一致したら、ある項目を書き換えるという処理です。
(今回は、消込区分を0→1にします。)
以下のコードで実行すると、確かにKEYが一致すれば、テーブルをUPDATE
しますが、一致しなくても正常処理とみなされるため、OKとエラーがそれぞれ
何件か分かりません。
CatchのところでカウントUPしても、一致しないのがここに来るわけじゃないみたいですね。
まだ、Try〜Catchの使い方がよくわかっていないのがダメだと思いますが、
UPDATEした、しないの判断はどのようにして分かるのでしょうか?
よろしくお願い致します。

・・・
Dim red As System.IO.StreamReader
red = New stem.IO.StreamReader"C:\XXXXX.TXT",System.Text.Encoding.Default)
Do While Not red.Peek() = -1
BatData = red.ReadLine.ToString

Dim Xxxxxban As Integer = BatData.Substring(0, 7)
Dim Xxxxym As Integer = BatData.Substring(7, 6)
Dim Xxxxno As Integer = BatData.Substring(13, 9)

Try
Dim SQL As String = ""
SQL += "update XXXXXTBL set 消込区分 = 1 where "
SQL += "(消込区分 = 0) AND "
SQL += "(〇〇番号 = " & Integer.Parse(Xxxxxban) & ") And "
SQL += "(□□年月 = " & Integer.Parse(Xxxxym) & ") AND "
SQL += "(△△番号 = " & Integer.Parse(Xxxxno) & ");"

  cmd.CommandText = SQL
cmd.ExecuteNonQuery()

Catch ex As DataException

End Try
Loop
  • 題名: Re[1]: Update時の未処理件数
  • 著者: SH
  • 日時: 2004/08/06 19:39:06
  • ID: 5439
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
Shinoさんこんばんわ。

Try 〜Catchでカウントアップは出来ません。
エラーが起きれば終わってしまいますよ。。
Catchに来るのはExceptionなので、
コレだとDBのエラーが起きたときにExceptionが来るわけです。
例えば、SQL文がおかしい。とか。

Catchの部分には、エラーの原因等をわかるようにする処理を入れるべきですね。
例えば、SQL文を出力するとか。。

で、件数ですが、ExecuteNonQuery()は、
そのSQL文に影響を受けた件数を返してくれます。
なので、変数を用意して、ExecuteNonQuery()の戻り値をカウントすればOKかと。
Shinoさん

> まだ、Try〜Catchの使い方がよくわかっていないのがダメだと思いますが、

DBを扱うシステムの場合、
トランザクションの管理とか、
DBの切断のタイミングとかが結構重要だと思いますよ。

SQL発行時になんらかのエラーが起きた場合、
DBの切断をしないとDBは固まってしまいます。
なので、CatchでExceptionを受信したら(しなくても)、
DBを切断する処理を入れたほうがいいです。

というか、Finallyで切断ですね。

あと、SQL実行でエラー起きたらロールバック、
正常終了ならコミットをするようにしましょう。
SHさん、こんばんは。

ホントに毎回のようにつきあって頂いて感謝しています。
いろいろ調べて、以下のように書いてみました。

> CatchでExceptionを受信したら(しなくても)、
> DBを切断する処理を入れたほうがいいです。
> というか、Finallyで切断ですね。
>
> あと、SQL実行でエラー起きたらロールバック、
> 正常終了ならコミットをするようにしましょう。

以上のSHさんが、おっしゃったことが実現されているでしょうか?
見よう見真似で書いたので・・・。


cone.Open()
trans = cone.BeginTransaction

cmd.Connection = cone
cmd.Transaction = trans

Dim BatData As String
Dim i As Integer = 0
Dim j As Integer = 0
Dim chk As Integer

Dim red As System.IO.StreamReader
red = New System.IO.StreamReader("C:\henrei.TXT", System.Text.Encoding.Default)
Do While Not red.Peek() = -1
BatData = red.ReadLine.ToString

(省略)

Try
(省略)

cmd.CommandText = SQL
chk = cmd.ExecuteNonQuery()

  If chk = 0 Then
j = j + 1
Else
i = i + 1
End If

Finally
Try

Catch ex As DataException
MsgBox("SQL")
red.Close()

trans.Rollback()
cone.Close()
End Try
End Try
Loop

MsgBox("更新OK・・・" & i & "件")
MsgBox("エラー・・・" & j & "件")

red.Close()

trans.Commit()
cone.Close()
Shinoさん、こんばんは。

なんか、Finallyを勘違いしているみたいだけど、

Try
 '処理
Catch
 '処理中に例外が発生した場合に通過
Finally
 'Tryが終わる時に必ず通過
End Try
だよ。つまり例外が有ろうが無かろうが、Finallyの中は通るということです。
非同期のADO.NETについてなら私のサイトにサンプルがありますので、参考にしてみてください。Try Catch、Rollback等も有るのでわかると思います。
うーん。。
ちょっと違いますね^^;

まずは、更新OK/エラー件数は抜きにして考えるようにしちゃいますね。
ちょっと直させてもらいました。
コレで上手くいくかちょっと不安ですが・・・

Try-Catchの考え方ですが、
ある処理の間にエラーが起きた場合、
それを受信するのがTry-Catchです。

書式は、

Try
 "処理"
Catch "○○エラー"
 "○○エラー時の処理"
Finally
 "何が起きようがする処理"
End Try

です。

で、Try-Catchではさむのは、エラーが起きる可能性がある部分で、
Catchには、起こりうるエラーを書きます。
Finallyは、エラーが起きようと必ず行う処理を記述します。
今回だと、DBのClose処理がコレにあたります。
Exceptionは他のCatchで記述していないエラーが起きたとき取得できるので、
必ず書きましょう。

Commit()は、そこまでに投げたSQLを確定するというイメージです。
エラーが起きた場合、そこまでUPDATEしたデータは反映させたいのであれば、
SQL実行後毎回コミットすればいいですし、
ファイルの全部を更新できなければその一連の処理はなかったことにしたのであれば、CommitはLoopの後に一回だけすればOKです。

但し、Commitを毎回やるのと1回だけやるのでは、
処理の時間はかなり違います。

とりあえず、ここまで出来るようにしましょう。
件数の取得は後からでも出来ますし。


cone.Open()
trans = cone.BeginTransaction

cmd.Connection = cone
cmd.Transaction = trans

Dim BatData As String
Dim cnt As Integer = 0
Dim chk As Integer

Dim red As System.IO.StreamReader

Try

red = New System.IO.StreamReader("C:\henrei.TXT",System.Text.Encoding.Default)

Do While Not red.Peek() = -1
BatData = red.ReadLine.ToString

(省略)

cmd.CommandText = SQL
cmd.ExecuteNonQuery()

Loop

trans.Commit()

Catch ex As DataException
MsgBox(ex.message & "SQL=" & SQL)
trans.Rollback()

Catch ex As Exception
MsgBox(ex.message & "SQL=" & SQL)
trans.Rollback()

Finally
cone.Close()
red.Close()

End Try
おはようございます。

以下の様にしてみました。

Try下の
Dim red As System.IO.StreamReader
red = New System.IO.StreamReader("C:\XXX.TXT", System.Text.Encoding.Default)はコメントしています。
実際はもっと上の方に、
If System.IO.File.Exists("A:\XXX.txt") Then 〜で、
FPDにXXX.txtが存在するかどうかのチエックをした後で記述しています。

処理してみるとデータもうまく更新されました。Msgboxも思ったとおりに件数出ました。
また、わざとSQLの列名をかえてやってみました。(消込区分→消込ああ)
すると、「列名'消込ああ'は無効です。SQL=update〜」って出ました。
ex.messageと書くと、エラーのメッセージが入って来るんですね!また、勉強になりました。
で、カウントアップの方法は適切でしょうか?
お願い致します。

cone.Open()
trans = cone.BeginTransaction

cmd.Connection = cone
cmd.Transaction = trans

Dim BatData As String
Dim i As Integer = 0
Dim j As Integer = 0
Dim chk As Integer
Dim SQL As String

Try
'Dim red As System.IO.StreamReader
'red = New System.IO.StreamReader("C:\XXX.TXT",   System.Text.Encoding.Default)
Do While Not red.Peek() = -1
BatData = red.ReadLine.ToString

Tst_Hokenban = BatData.Substring(0, 7)
Dim Hokenban As Integer = BatData.Substring(0, 7)
Dim Toriym As Integer = BatData.Substring(7, 6)
Dim Datano As Integer = BatData.Substring(13, 9)

SQL = ""
SQL += "update DXSAIHEN set 消込区分 = 1 where "
SQL += "(消込区分 = 0) AND "
SQL += "(保険者番号 = " & Integer.Parse(Hokenban) & ") And "
SQL += "(取扱年月 = " & Integer.Parse(Toriym) & ") AND "
SQL += "(データ番号 = " & Integer.Parse(Datano) & ");"

cmd.CommandText = SQL
chk = cmd.ExecuteNonQuery()
If chk = 0 Then
j = j + 1
Else
i = i + 1
End If

Loop
trans.Commit()

Catch ex As DataException
MsgBox(ex.Message & "SQL=" & SQL)
trans.Rollback()

Catch ex As Exception
MsgBox(ex.Message & "SQL=" & SQL)
trans.Rollback()

Finally
cone.Close()
red.Close()

End Try

MsgBox("更新OK・・・" & i & "件")
MsgBox("エラー・・・" & j & "件")
Shinoさん、おはようございます。

うまくいったようでなによりです。
あとは正しくロールバックされるかをチェックした方がいいですね。

例えば、5件中3件目でエラーが起きるようにして、
1、2件目の内容が更新されていない。といううような確認ですね。

それと、エラーメッセージはどちらのExceptionで出ていましたか??
ここでは、DataExceptionではなく、
SQLExceptionが発生するような気がします。

Exceptionの方でキャッチされてるとしたら、
SQLExceptionを追加したほうがいかも。
というかDataExceptionは発生しないような気が・・・


>で、カウントアップの方法は適切でしょうか?

更新件数とエラー件数の定義によると思うのですが、
Where句をキーとして更新してみて、
更新対象のデータがなければ(0件なら)エラー、
それ以外ならOKということであれば大丈夫だと思います。

ただ、UPDATE文は、一回のSQLで複数件のデータが更新されるので、
Where句の条件に該当するデータが複数あった場合は問題ありませんか???
chkには0か1ではなく、更新された件数が入ってきます。

chk = cmd.ExecuteNonQuery()
If chk = 0 Then
j = j + 1
Else
i = i + 1
End If


これだと、条件によって複数のデータが更新されていた場合も、
1件しか更新されていないことになっちゃいますね。
i = i + chk
正しい更新件数はこうですね。
結果は変わらない気もしますが・・・

仕様がわかっていないので、気になるとしたらこれくらいですかね。
SHさん、またまたさっそくのレスありがとうございます。

> エラーメッセージはどちらのExceptionで出ていましたか??
> ここでは、DataExceptionではなく、
> SQLExceptionが発生するような気がします。

As DataEceptionではなく、As Exceptionの方で出ていました。
エラーの種類別に分けなかったら、Exception書けば全部来るみたいだから、
Exceptionのみ書いておいてもOKみたいですね。


> >で、カウントアップの方法は適切でしょうか?
>
> 更新件数とエラー件数の定義によると思うのですが、
> Where句をキーとして更新してみて、
> 更新対象のデータがなければ(0件なら)エラー、
> それ以外ならOKということであれば大丈夫だと思います。
上記どおりです。

> ただ、UPDATE文は、一回のSQLで複数件のデータが更新されるので、
> Where句の条件に該当するデータが複数あった場合は問題ありませんか???
> chkには0か1ではなく、更新された件数が入ってきます。
FPDから来るデータも、SQLのデータも重複なしという前提です。


他にも、追加や削除している場所があるので、同様に修正していきます。
ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板