- PR -

◆データベースのテーブルから指定した複数のレコードを削除したい。

投稿者投稿内容
One.net
大ベテラン
会議室デビュー日: 2008/03/01
投稿数: 202
投稿日時: 2008-08-11 15:48
【状況説明】
WindowsXP、VB2005EE Access2003 でWindowsアプリケーションを開発中です。
table1 の指定した複数のレコードを削除したく、次のコードを実行しましたが
「削除された行を通して、その行の情報にアクセスすることはできません。」と
エラーメッセージが表示されてしまいます。
コード:

Me.table1TableAdapter.Fill(Me.DataSet1.table1)
Dim dr As DataRow
Dim i, NN(10) As Integer
NN(0) = 2 : NN(1) = 4 : NN(2) = 6 : NN(3) = 8 : NN(4) = 10 : NN(5) = 12
For i = 0 To 5
For Each dr In DataSet1.table1.Rows
If CInt(dr("番号")) = NN(i) Then
dr.Delete()
End If
Next
Next
'--更新処理
Me.Validate()
Me.table1BindingSource.EndEdit()
table1TableAdapter.Update(Me.DataSet1.table1)



このことは i = 0 でDataRowオブジェクトにDeleteマークを付けてから i = 1 で
再度参照しようとしたのでエラーが発生するのだろうと考え、1回だけ削除する
次のようなコードでテストすると正常に CInt(dr("番号")) = 2 のレコードだけ
削除されました。
コード:

Me.table1TableAdapter.Fill(Me.DataSet1.table1)
Dim dr As DataRow
For Each dr In DataSet1.table1.Rows
If CInt(dr("番号")) = 2 Then
dr.Delete()
End If
Next
'--更新処理
Me.Validate()
Me.table1BindingSource.EndEdit()
table1TableAdapter.Update(Me.DataSet1.table1)



【問題点】
上記のように指定した複数のレコードを削除する方法をご指導いただきたいのですが
よろしくお願いいたします。



修正:件名に「指定した」を挿入

[ メッセージ編集済み 編集者: One.net 編集日時 2008-08-11 16:51 ]
こあら
大ベテラン
会議室デビュー日: 2007/06/26
投稿数: 157
投稿日時: 2008-08-11 17:24
引用:
1回だけ削除する次のようなコードでテストすると
正常に CInt(dr("番号")) = 2 のレコードだけ削除されました。


だとすると、上記チェックを「削除対象の番号の配列に存在するか?」にすれば良いんじゃないでしょうか。
Toshi
ベテラン
会議室デビュー日: 2007/09/18
投稿数: 68
お住まい・勤務地: 関東のどっか
投稿日時: 2008-08-11 18:26
単純に逆にすればいいのでは・・・
コード:
For j = 0 To DataSet1.table1.Rows.Count
     For i = 0 To 5
           If CInt(DataSet1.table1.Rows(j)("番号")) = NN(i) Then 
                 DataSet1.table1.Rows(j).Delete()
           End If
     Next
Next



ビルド等、確認していませんのでご了承を。

あと、FOR EACH よりは FOR のほうがよろしいかと
http://msdn.microsoft.com/ja-jp/library/5ebk1751.aspx
こあら
大ベテラン
会議室デビュー日: 2007/06/26
投稿数: 157
投稿日時: 2008-08-11 18:41
> 単純に逆

exit forしないと同じこと(Deleteマークが付いたRowを再度参照)が起こりませんか?
Toshi
ベテラン
会議室デビュー日: 2007/09/18
投稿数: 68
お住まい・勤務地: 関東のどっか
投稿日時: 2008-08-11 18:55
引用:

> 単純に逆

exit forしないと同じこと(Deleteマークが付いたRowを再度参照)が起こりませんか?



ほんとですね・・・
指摘ありがとうございます。

念のため、修正版を
コード:
For j = 0 To DataSet1.table1.Rows.Count
     For i = 0 To 5
           If CInt(DataSet1.table1.Rows(j)("番号")) = NN(i) Then 
                 DataSet1.table1.Rows(j).Delete()
                 Exit For
           End If
     Next
Next


One.net
大ベテラン
会議室デビュー日: 2008/03/01
投稿数: 202
投稿日時: 2008-08-11 23:41
夕方から外出していましたもので、回答をいただきながら失礼いたしました。

こあらさん、Toshiさん、ありがとうございます。
早速指導いただきましたとおりテストしましたら正常に削除できました。
ただし、「For j = 0 To DataSet1.table1.Rows.Count」をまだ勉強して
いないので、とりあえず次のようにしてテストしました。
コード:

Dim dr As DataRow
Dim ZZ, i, NN(5) As Integer
NN(0) = 2 : NN(1) = 4 : NN(2) = 6 : NN(3) = 8 : NN(4) = 10 : NN(5) = 12
For Each dr In DataSet1.table1.Rows
ZZ = CInt(dr("番号"))
For i = 0 To 5
If ZZ = NN(i) Then
dr.Delete()
End If
Next
Next




こあらさん。追加の回答ありがとうございます。
>「exit forしないと同じことが起こりませんか?」
とのご指摘をいただきましたが、「Deleteマークが付いたRowを再度参照」の
理解が出来ませんがコードをたどって勉強します。ありがとうございました。

ところで外出途中で自分なりに解決方法を考えていましたが
「接続型のデータアクセス」でDELETE文を使うことを考えてみました。
まだテストしていませんが、試してみて結果をこのスレッドに報告します。
以上取り急ぎお礼まで・・・

[ メッセージ編集済み 編集者: One.net 編集日時 2008-08-12 00:00 ]
こあら
大ベテラン
会議室デビュー日: 2007/06/26
投稿数: 157
投稿日時: 2008-08-12 10:07
引用:

「exit forしないと同じことが起こりませんか?」とのご指摘をいただきましたが、
「Deleteマークが付いたRowを再度参照」の理解が出来ません



話がかみ合っていない印象を受けました。
もう一度最初のご自分の投稿からすべて読み返して頂けませんか。

ちなみに
コード:

For i = 0 To 5
If ZZ = NN(i) Then
dr.Delete()
End If
Next

上記コードは、
コード:

If NN.indexOf(CInt(dr("番号"))) <> -1 Then
dr.Delete()
End If

のように書けるのではないか?というのが私の最初のコメントの意味です。
これならZZのような一時的な変数が不要(forループしないので当然exit forも不要)だと考えました。


[追記]
MSDNによるとIndexOfは以下のように記述するそうです。
コード:

If Array.IndexOf(NN, CInt(dr("番号"))) <> -1 Then
dr.Delete()
End If


[/追記]

[ メッセージ編集済み 編集者: こあら 編集日時 2008-08-12 14:17 ]
One.net
大ベテラン
会議室デビュー日: 2008/03/01
投稿数: 202
投稿日時: 2008-08-12 11:52
こあらさん、ありがとうございます。
IndexOfメソッドは NN文字列の中にパラメータ指定した文字列存在チェック(又は最初に見つかった位置)
に使うもので数字(NN)には使用できない思っていましたし、配列変数(NN())の全てをチェックできないと
思っています。

また実際のご指摘のコードをテストしますと「この引数の数を受け付ける"IndexOf"がないため
オーバーロードの解決に失敗しました」と表示されビルドが失敗します。
何か間違ってテストしているのでしょうか。

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