2017-12-02 18 views
1

Accessデータベースには1つのテーブルが含まれています。すべてのレコードには昇順の数字がありますが、キーとしてはなりません。これは、レコードの外観を注文するためにVBアプリケーションで使用されています。選択したすべてのレコードをアプリケーションで削除する方法はわかっていますが、残りの9つのレコードに新しい昇順の数字を付けて更新する方法は見つけられません。たとえば、5番目のレコードを削除した場合、残りのレコードをカウントして新しい昇順の数字を返すようにします。VB.NET - MS Accessデータベース内のレコードを1つ削除し、残りのレコードに新しい昇順番号を付けて更新します。

私はこのようなことをしましたが、もちろんそれは仕事をしません...

Imports System.Data.OleDb 

Public Class ApplicationForm 

    Public Provider As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source =" 
    Public DataFile As String = "database.accdb" 
    Public ConnString As String = Provider & DataFile 
    Public MyConnection As OleDbConnection = New OleDbConnection 

    Private Sub AppsPaths_DelButton_Click(sender As Object, e As EventArgs) Handles AppsPaths_DelButton.Click 
     MyConnection.ConnectionString = ConnString 
     MyConnection.Open() 

     Dim DBCount As Integer = AppsCount_Label2.Text 
     Dim i As Integer = 0 
     Dim strDelete As String 
     Dim strUpdate As String 
     strDelete = "DELETE FROM ApplicationsPaths WHERE TagNum = '" & AppToDel_Label.Text & "'" 
     Dim cmdDelete As OleDbCommand = New OleDbCommand(strDelete, MyConnection) 
     Do 
      strUpdate = "UPDATE [ApplicationsPaths] SET [TagNum] = '" & i.ToString & "'" 
      i += 1 
     Loop Until i = DBCount 
     Dim cmdUpdate As OleDbCommand = New OleDbCommand(strUpdate, MyConnection) 
     Try 
      cmdDelete.ExecuteNonQuery() 
      cmdDelete.Dispose() 
      cmdUpdate.ExecuteNonQuery() 
      cmdUpdate.Dispose() 
      MyConnection.Close() 
     Catch ex As Exception 
      MsgBox(ex.Message) 
     End Try 
    End Sub 

End Class 
+2

なぜ迷惑でしょうか?順序付けのために重要なのは相対値だけであり、絶対値ではありません。そこに穴を残すだけで、ソート結果はまったく同じになります。 – jmcilhinney

+0

いいえアプリケーションはプログラムで追加されたコントロールにすべてのレコードをロードし、この昇順の番号を使用するため、できません。したがって、最後のレコードを除く他のレコードを削除した場合、アプリケーションは何もロードしません。私のアプリケーションを通して新しいレコードを追加しようとすると、同じことが起こります。最後のものを除いて1つのレコードが欠落していても、すべてがうんざりです! –

答えて

3

手順のいずれかに連続する番号が必要な場合は、テーブルの代わりに実行中の合計型の計算を使用することをお勧めします。私はVB.Net上でブラシアップされていないが、私はあなたがテーブルを参照するように簡単にクエリを参照することができると思います。ここで

が欠落しているIDの持つデータの私のテーブルです:

table

このSQLクエリは、固有の連続したIDのIncIDと呼ばれるが用意されています

SELECT DCount("id","table2","id<=" & [id]) AS IncID, thing FROM Table2; 

そして、ここではその結果です:

query result

+1

実行中のカウント/合計を表示するDCount/DSumメソッドは、問題のプラットフォームであるVB.NETとAccessの両方を開発した会社のお勧めの方法です。 "10,000行更新する必要がある場合を想像してみてください。計算を処理するためにデータベースが構築されました。また、確かめるために、**私は100,000レコードでテストしましたが、結果は瞬時でした。** – ashleedawg

1

更新ステートメントを1回しか呼び出さず、更新ステートメントに条件が含まれていないため、すべての行が更新されるため、コードが機能しません。ループ内の更新ステートメントを呼び出し、条件を含めると、一度に1つの行のみが更新されます。私はAppsCount_Label2がそのテーブルの合計行を保持していると仮定します。カウンタが削除されたものと等しい場合は、ステートメントの呼び出しをスキップします。

Private Sub AppsPaths_DelButton_Click(sender As Object, e As EventArgs) Handles AppsPaths_DelButton.Click 
    MyConnection.ConnectionString = ConnString 
    MyConnection.Open() 

    Dim DBCount As Integer = AppsCount_Label2.Text 
    Dim i As Integer = 0, j As Integer = 0 
    Dim strDelete As String 
    Dim strUpdate As String 
    strDelete = "DELETE FROM ApplicationsPaths WHERE TagNum = '" & AppToDel_Label.Text & "'" 

    Try 
     Dim cmdDelete As OleDbCommand = New OleDbCommand(strDelete, MyConnection) 
     cmdDelete.ExecuteNonQuery() 
     cmdDelete.Dispose() 

     Do 
      i += 1 
      If i <> AppToDel_Label.Text Then 
       j += 1 
       strUpdate = "UPDATE [ApplicationsPaths] SET [TagNum] = '" & j.ToString & "' WHERE TagNum = '" & i.ToString & "'" 
       Dim cmdUpdate As OleDbCommand = New OleDbCommand(strUpdate, MyConnection) 
       cmdUpdate.ExecuteNonQuery() 
       cmdUpdate.Dispose() 
      End If 
     Loop Until i = DBCount 

     MyConnection.Close() 
    Catch ex As Exception 
     MsgBox(ex.Message) 
    End Try 
End Sub 

のは、あなたが5行を持っていて、delete文がDELETE FROM ApplicationsPaths WHERE TagNum = '2'あるTagNum = 2を削除しましょう。各反復で更新文は、このようなものです:

変数i = 2(TagNumを削除した)、それは更新ステートメントと変数jの増分の実行をスキップし
UPDATE [ApplicationsPaths] SET [TagNum] = '1' WHERE TagNum = '1' 
UPDATE [ApplicationsPaths] SET [TagNum] = '2' WHERE TagNum = '3' 
UPDATE [ApplicationsPaths] SET [TagNum] = '3' WHERE TagNum = '4' 
UPDATE [ApplicationsPaths] SET [TagNum] = '4' WHERE TagNum = '5' 

。しかし、このステートメントは、更新ステートメントのn-1回の実行があり、nは削除ステートメントの前の行数であるため、テーブルに多数の行があると、このコードは良くありません。 RDBMSは、個々の行ではなく行のセットで動作します。したがって、バッチ内のすべてのレコードを更新する方がよいでしょう。コードを修正しましょう。

まず、表のTagNum型を数値型に更新します。

Private Sub AppsPaths_DelButton_Click(sender As Object, e As EventArgs) Handles AppsPaths_DelButton.Click 
    Try 
     MyConnection.ConnectionString = ConnString 
     MyConnection.Open() 
     Dim strQuery As String 

     Dim DBCount As Integer = AppsCount_Label2.Text 

     strQuery = "DELETE FROM ApplicationsPaths WHERE TagNum = " & AppToDel_Label.Text 
     Using cmd = New OleDbCommand(strQuery, MyConnection) 
      cmd.ExecuteNonQuery() 
     End Using 

     strQuery = "UPDATE ApplicationsPaths SET TagNum = TagNum - 1 WHERE TagNum > " & AppToDel_Label.Text 
     Using cmd = New OleDbCommand(strQuery, MyConnection) 
      cmd.ExecuteNonQuery() 
     End Using 

     MyConnection.Close() 
    Catch ex As Exception 
     MsgBox(ex.Message) 
    End Try 
End Sub 

まだ5行あり、TagNum = 3を削除したとします。 deleteステートメントはDELETE FROM ApplicationsPaths WHERE TagNum = 3です。更新ステートメントはUPDATE ApplicationsPaths SET TagNum = TagNum - 1 WHERE TagNum > 3です。更新文は一度だけ実行され、2行(TagNum = 4およびTagNum = 5)にのみ影響します。何千もの行があると想像してください。最初のコードを使用する場合、いくつの更新ステートメントが実行されますか?変数iがAppToDel_Labelよりも低いときに更新の実行をスキップするように最初のコードを最適化することはできますが、何度も繰り返し実行されます。

EDIT:不要な更新をスキップするように最初のコードを最適化します。あなたが5行を持っているとTagNum = 3を削除した場合

MyConnection.ConnectionString = ConnString 
MyConnection.Open() 

Dim DBCount As Integer = AppsCount_Label2.Text 
Dim i As Integer = 0, j As Integer = AppToDel_Label.Text 
Dim strDelete As String 
Dim strUpdate As String 
strDelete = "DELETE FROM ApplicationsPaths WHERE TagNum = '" & AppToDel_Label.Text & "'" 

Try 
    Dim cmdDelete As OleDbCommand = New OleDbCommand(strDelete, MyConnection) 
    cmdDelete.ExecuteNonQuery() 
    cmdDelete.Dispose() 

    Do 
     i += 1 
     If i > AppToDel_Label.Text Then 
      strUpdate = "UPDATE [ApplicationsPaths] SET [TagNum] = '" & j.ToString & "' WHERE TagNum = '" & i.ToString & "'" 
      Dim cmdUpdate As OleDbCommand = New OleDbCommand(strUpdate, MyConnection) 
      cmdUpdate.ExecuteNonQuery() 
      cmdUpdate.Dispose() 
      j += 1 
     End If 
    Loop Until i = DBCount 

    MyConnection.Close() 
Catch ex As Exception 
    MsgBox(ex.Message) 
End Try 

は更新文は、次のとおりです。TagNum値が変更されないため

UPDATE [ApplicationsPaths] SET [TagNum] = '3' WHERE TagNum = '4' 
UPDATE [ApplicationsPaths] SET [TagNum] = '4' WHERE TagNum = '5' 

TagNum = 1とTagNum = 2更新文は必要ありません。しかし、行を個別に更新するためにたくさんある場合、それはまだ良くありません。

+0

** DCount **メソッドは正常です。コメント[上記](https://stackoverflow.com/a/47606998/8112776)を参照してください。 – ashleedawg

+0

@ashleedawg DCountについてのコメントを削除しました。 – Han

関連する問題