2017-12-02 9 views
1

하나의 테이블과 예를 들어 10 개의 레코드가 포함 된 Access DB 파일이 있습니다. 모든 레코드에는 오름차순 숫자가 있지만 키가 아닙니다. VB 애플리케이션에서 레코드의 모양을 지정하는 데 사용됩니다. 내 응용 프로그램을 통해 선택한 모든 레코드를 삭제하는 방법을 알고 있지만 9 개의 레코드를 새로 고치는 방법을 찾을 수 없습니다. 예를 들어 다섯 번째 레코드를 삭제하면 내 앱이 나머지 레코드 수를 계산하고 새롭게 오름차순 번호를 부여하기를 원합니다 ...VB.NET - MS Access 데이터베이스에서 하나의 레코드를 삭제하고 새 오름차순 번호를 부여하여 나머지를 업데이트하십시오.

나는이 작업을 수행했으나 물론 작업을 수행하지 않습니다 ...

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

아니요 응용 프로그램에서 모든 레코드를 프로그래밍 방식으로 추가 된 컨트롤로로드하고이 오름차순 번호를 사용하기 때문에 저는이 작업을 수행 할 수 없습니다. 따라서 마지막 레코드를 제외한 다른 레코드를 제거하면 응용 프로그램에서 아무 것도로드하지 않거나 일부 레코드를로드합니다. 내 응용 프로그램을 통해 새 레코드를 추가하려고하면 동일한 문제가 발생합니다. 마지막 레코드를 제외하고 하나의 레코드가 누락 된 경우라도 모두 엉망입니다 !!! –

답변

3

하나의 프로 시저에 연속 번호가 필요한 경우 테이블 대신 누적 합계 계산을 사용하는 것이 좋습니다. 나는 VB.Net에서 솔질하지 못했지만 테이블을 참조하는 것만 큼 쉽게 쿼리를 참조 할 수 있다고 생각합니다. 이 SQL 쿼리는 고유의 연속 ID의 IncID라고 제공

table

: 여기

누락 된 ID의와 데이터의 내 테이블

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

그리고 여기 결과입니다

query result

+1

문제의 플랫폼 인 VB.NET과 Access를 모두 개발 한 회사에서 실행 횟수/총계를 표시하는 DCount/DSum 방법이 권장되는 방법입니다. "10,000 개의 행을 업데이트해야한다고 상상해보십시오."단단한 논리가 아닙니다. 데이터베이스는 계산을 처리하도록 설계되었습니다. 또한 확실하게하기 위해, ** 나는 방금 100,000 개의 레코드로 테스트했는데 그 결과는 즉각적이었습니다. ** – ashleedawg

1

업데이트 구문을 한 번만 호출하고 업데이트 구문에 조건이 없으므로 모든 행이 업데이트되므로 코드가 작동하지 않습니다. 루프에서 update 문을 호출하고 조건을 포함하면 한 번에 한 행만 업데이트됩니다. 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 FROM ApplicationsPaths WHERE TagNum = 3입니다. 업데이트 문은 UPDATE ApplicationsPaths SET TagNum = TagNum - 1 WHERE TagNum > 3입니다. update 문은 한 번만 실행되며 2 행 (TagNum = 4 및 TagNum = 5)에만 영향을 미칩니다. 수천 개의 행이 있다고 상상해보십시오. 첫 번째 코드를 사용하면 몇 개의 update 문이 실행됩니까? 변수 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