쿼리 실행 중 오류 3340 ''쿼리가 손상되었습니다. DoCmd.RunSQL


83

KB 4484127을 해결하는 Office 2010 용 Windows 업데이트를 설치 한 WHERE 절이 포함 된 쿼리를 실행하는 동안 오류가 발생합니다.

예를 들어이 쿼리를 실행하면

DoCmd.RunSQL "update users set uname= 'bob' where usercode=1"

이 오류가 발생합니다 :

오류 번호 = 3340 ''쿼리가 손상되었습니다

해당 업데이트 는 현재 여전히 설치되어 있습니다.

Microsoft Office 2010 서비스 팩 2 업데이트 448127을 보여주는 스크린 샷

쿼리를 성공적으로 실행하려면 어떻게해야합니까? 이 업데이트를 제거해야합니까?

답변:


92

요약

이 버그는 2019 년 11 월 12 일에 릴리스 된 Office 업데이트로 인해 알려진 버그입니다. 이 버그는 Microsoft에서 현재 지원하는 모든 버전의 Access (Access 2010에서 365까지)에 영향을줍니다.

이 버그가 수정되었습니다.

  • C2R (Click-to-Run) 버전의 Office를 사용하는 경우 "지금 업데이트"를 사용하십시오 .
    • Access 2010 C2R : 빌드 7243.5000에서 수정되었습니다.
    • Access 2013 C2R : 빌드 5197.1000에서 수정되었습니다.
    • Access 2016 C2R : 빌드 12130.20390에서 수정되었습니다.
    • Access 2019 (v1910) : 빌드 12130.20390에서 수정되었습니다.
    • Access 2019 (볼륨 라이센스) : 빌드 10353.20037에서 수정되었습니다.
    • Office 365 월별 채널 : 빌드 12130.20390에서 수정되었습니다.
    • Office 365 반기 : 빌드 11328.20480에서 수정되었습니다.
    • Office 365 반기 확장 : 빌드 10730.20422에서 수정 됨
    • Office 365 반기 대상 : 빌드 11929.20494에서 해결됨
  • MSI 버전의 Office를 사용하는 경우 Office 버전과 일치하는 업데이트를 설치하십시오. 이러한 모든 패치는 Microsoft Update에서 릴리스되었으므로 보류중인 모든 Windows Update를 설치 하면 충분합니다.

최소한의 재현 예제는 다음과 같습니다.

  1. 새 Access 데이터베이스를 작성하십시오.
  2. 기본 ID 필드와 Long Integer 필드 "myint"를 사용하여 비어있는 새 테이블 "Table1"을 작성하십시오.
  3. VBA 편집기의 직접 실행 창에서 다음 코드를 실행하십시오.

    CurrentDb.Execute "UPDATE Table1 SET myint = 1 WHERE myint = 1"

예상 결과 : 명령문이 완료되었습니다.

버그가있는 업데이트 중 하나가 설치된 실제 결과 : 런타임 오류 3340이 발생합니다 ( "쿼리 ''이 손상되었습니다").


관련된 링크들:


9
이 게시물 은 64 비트 Access 런타임 및 OLEDB를 사용하는 경우 동일한 오류가 발생합니다. 무서운 것은 Access를 사용하여 데이터를 저장하는 많은 응용 프로그램을 사용할 수 없게 만듭니다.
Erik A

4
난 그냥 오피스 2013 32 비트 시스템을 확인하고 해당 컴퓨터에 업데이트에 대한 UUID입니다 90150000-006E-0409-0000-0000000FF1CE... 그의 -0409-하지 -0407-.
Gord Thompson

4
방금 Office 2013 64 비트가있는 사무실의 다른 컴퓨터를 확인했으며 UUID -006E-0409-도 있습니다. 두 컴퓨터에는 Microsoft Office 2013 서비스 팩 1 (KB2850036)이 설치되어 있습니다.
고르 드 톰슨

4
Office 2010 Pro Plus (SP2)의 {90140000-0011-0000-0000-0000000FF1CE}경우 배치 스크립트에서 사용해야 했습니다. 참고 {9014...없습니다{9114..}
AdamsTips

2
문제를 해결하기 위해 공식 업데이트로 패치했지만 여전히 오류가 발생합니다. 다른 사람이 그 문제를 겪었습니까?
user218076

33

가장 간단한 솔루션

내 사용자에게는 12 월 10 일까지 거의 한 달 동안 Microsoft의 수정 릴리스를 기다리는 것은 옵션이 아닙니다. 여러 정부의 잠긴 워크 스테이션에서 문제가되는 Microsoft 업데이트를 제거하지도 않습니다.

해결 방법을 적용해야하지만 Microsoft가 제안한 각 테이블에 대해 쿼리를 작성하고 대체하는 것과는 전혀 다릅니다.

해결책은 테이블 이름을 테이블에서 간단한 (SELECT * FROM Table)쿼리로 직접 바꾸는 것 입니다.UPDATE 명령 입니다. 추가 쿼리, 테이블 또는 함수를 생성하고 저장할 필요가 없습니다.

예:

전에:

UPDATE Table1 SET Field1 = "x" WHERE (Field2=1);  

후:

UPDATE (SELECT * FROM Table1) SET Field1 = "x" WHERE (Field2=1);  

여러 데이터베이스와 응용 프로그램 (및 나중에 롤백)에서 구현하기가 훨씬 쉬워야합니다.


20

이것은 Windows 업데이트 문제가 아니라 November Patch Tuesday Office 릴리스에서 도입 된 문제입니다. 보안 취약점을 수정하기 위해 변경하면 일부 합법적 인 쿼리가 손상된 것으로보고됩니다. 이 변경은 보안 수정이므로 2010, 2013, 2016, 2019 및 O365를 포함한 모든 Office 빌드에 영향을줍니다.

버그는 모든 채널에서 수정되었지만 제공시기는 사용중인 채널에 따라 다릅니다.

2010 년, 2013 년, 2016 년 MSI 및 2019 볼륨 라이선스 빌드 및 O365 반기 채널의 경우 수정 사항은 12 월 패치 화요일 빌드, 12 월 10 일에 있습니다. O365, 월별 채널 및 내부자의 경우이 문제가 해결됩니다. 10 월 포크가 출시되면 현재 11 월 24 일로 예정되어 있습니다.

반기 채널의 경우이 버그는 11328.20468에 도입되었으며 11328 년 12 월에 릴리스되었지만 한 번에 모든 사람에게 배포되지는 않습니다. 가능한 경우 12 월 10 일까지 업데이트를 보류 할 수 있습니다.

조건이 지정된 단일 테이블에 대한 업데이트 쿼리에 대해이 문제가 발생합니다 (따라서 다른 유형의 쿼리 나 테이블의 모든 행을 업데이트하는 쿼리 또는 다른 쿼리의 결과 집합을 업데이트하는 쿼리). 따라서 대부분의 경우 가장 간단한 해결 방법은 쿼리를 직접 업데이트하지 않고 업데이트 쿼리를 변경하여 테이블에서 모든 항목을 선택하는 다른 쿼리를 업데이트하는 것입니다.

즉, 다음과 같은 쿼리가 있으면

UPDATE Table1 SET Table1.Field1 = "x" WHERE ([Table1].[Field2]=1);

그런 다음 다음과 같이 정의 된 새 쿼리 (Query1)를 작성하십시오.

Select * from Table1;

원래 검색어를 다음과 같이 업데이트하십시오.

UPDATE Query1 SET Query1.Field1 = "x" WHERE ([Query1].[Field2]=1);

공식 페이지 : 액세스 오류 : "쿼리가 손상되었습니다"


13
실제로 여러 응용 프로그램에 배포 된 수십만 줄의 코드로 가서 데이터 행을 간단하게 업데이트하는 모든 SQL 업데이트를 수정한다는 사실을 직설적으로 말하고 있습니까? 오늘 새 쿼리를 작성하고 지금 당장 이러한 해결 방법이 가능하다고 가정합니다. 그러나 기존 코드 및 응용 프로그램의 경우 SQL 업데이트를 변경해야한다는 아이디어는 물론 어떤 방식으로도 probelm 해결에 대한 실용적인 접근 방식이 아닙니다.
Albert D. Kallal

5
@ AlbertD.Kallal, MVP 목록에서 문제의 원인에 대한 설명을 참조한다는 것을 알아야합니다. 문제를 해결하는 방법은 실제로 귀하에게 달려 있으며 시나리오에 적합한 것입니다. 여기에 설명 된 방법은 몇 가지 중 하나 일뿐입니다.
구스타프

1
@ AlbertD.Kallal 테이블 이름을 바꾸거나 이전 테이블 이름으로 QueryDefs를 생성해서는 안됩니까? (나는 그것을 테스트하고 작동하는 경우 스크립트를 게시합니다)
ComputerVersteher

예를 들어 테이블 "users"의 이름을 "userst"로 바꾸고 쿼리 이름 "users"를 만들면 프로그래밍 없이도 할 수 있습니다. 그러면 프로그래밍 chane 없이도 작동합니다 ....
Zvi Redler

9
@ AlbertD.Kallal : 나는 당신의 고통을 공유합니다-이것이 VC 런타임 라이브러리에 영향을 미치는 버그라면 MS가 한 달 동안 수정을 지연시키고 "다시 작성, 재 컴파일 및 재배치"해결 방법을 제안하지 않을 것이라고 생각합니다. (공평하게 말하면, 그들은 8 월 말에 VBA 문제를 신속하게 수정하고 발표했습니다.) 그러나 메신저를 쏘지 마십시오-구스타프는 MS 직원이 아닌 것 같습니다. 그들이 패치를 더 일찍 재고하고 릴리스하기를 바랍니다. 결국 Access DB 엔진을 사용하는 다른 언어로 작성된 응용 프로그램 에도 영향을줍니다 .
Heinzi

15

이 문제를 일시적으로 해결하려면 사용중인 Access 버전에 따라 다릅니다.
Access 2010 제거 업데이트 KB4484127
액세스 2013 제거 업데이트 KB4484119
액세스 2016 제거 업데이트 KB4484113
액세스 2019 필요한 경우 (tbc). 버전 1808 (빌드 10352.20042)에서 버전 1808로 다운 그레이드 (빌드 10351.20054)
오피스 버전 1910 (빌드 12130.20344)에서 이전 빌드로 365 PROPLUS 다운 그레이드를 참조 https://support.microsoft.com/en-gb/help/2770432/ 사무실 2013- 또는 사무실 2016-clic의 이전 버전으로 되 돌리는 방법


제거했지만 다음에 Windows를 시작할 때 다시 설치했습니다. 다시 설치하지 못하게하려면 어떻게합니까?
dsteele

5
@dsteele MSI 버전이고 WSUS가없는 경우 support.microsoft.com/en-us/help/3073930/… 문제 해결 도구를 사용하십시오. 오피스 계정 설정에서 CTR 해제 업데이트에 ..
ComputerVersteher

5

우리와 고객은 지난 이틀 동안이 문제로 어려움을 겪고 마지막으로 몇 가지 솔루션과 함께 문제에 대해 자세히 논의하기위한 논문을 작성했습니다. http://fmsinc.com/MicrosoftAccess/Errors/query_is_corrupt/

여기에는 로컬 테이블, 연결된 Access 테이블 및 연결된 SQL Server 테이블에서 업데이트 쿼리를 실행할 때 Access 솔루션에 영향을 미친다는 연구 결과가 포함되어 있습니다.

또한 ACE (Access Database Engine)를 사용하여 ADO를 사용하여 Access 데이터베이스에 연결하는 비 Microsoft Access 솔루션에도 영향을줍니다. 여기에는 Visual Studio (WinForm) 앱, VB6 앱 및 Access 또는 Office가 설치되어 있지 않은 컴퓨터의 Access 데이터베이스를 업데이트하는 웹 사이트도 포함됩니다.

이 충돌은 PowerBI, Power Query, SSMA 등과 같은 ACE를 사용하는 Microsoft 앱 (확인되지 ​​않음) 및 VBA를 사용하여 Access 데이터베이스를 수정하는 Excel, PowerPoint 또는 Word와 같은 다른 프로그램에도 영향을 줄 수 있습니다.

문제가되는 보안 업데이트를 명백히 제거하는 것 외에도, PC를 제어 할 수없는 외부 고객에게 Access 응용 프로그램의 권한 또는 배포로 인해 제거 할 수없는 경우 몇 가지 옵션도 포함됩니다. 여기에는 보안 업데이트의 영향을받지 않으므로 모든 업데이트 쿼리 변경 및 Access 2007 (소매 또는 런타임)을 사용하여 Access 응용 프로그램 배포가 포함됩니다.


4

다음 모듈을 사용하여 Microsoft가 제안한 해결 방법 (테이블 대신 쿼리 사용)을 자동으로 구현하십시오. 예방책으로 먼저 데이터베이스를 백업하십시오.

AddWorkaroundForCorruptedQueryIssue()임시 해결책을 추가하고 RemoveWorkaroundForCorruptedQueryIssue()언제든지 제거하는 데 사용하십시오 .

Option Compare Database
Option Explicit

Private Const WorkaroundTableSuffix As String = "_Table"

Public Sub AddWorkaroundForCorruptedQueryIssue()
    On Error Resume Next

    With CurrentDb
        Dim tableDef As tableDef
        For Each tableDef In .tableDefs
            Dim isSystemTable As Boolean
            isSystemTable = tableDef.Attributes And dbSystemObject

            If Not EndsWith(tableDef.Name, WorkaroundTableSuffix) And Not isSystemTable Then
                Dim originalTableName As String
                originalTableName = tableDef.Name

                tableDef.Name = tableDef.Name & WorkaroundTableSuffix

                Call .CreateQueryDef(originalTableName, "select * from [" & tableDef.Name & "]")

                Debug.Print "OldTableName/NewQueryName" & vbTab & "[" & originalTableName & "]" & vbTab & _
                            "NewTableName" & vbTab & "[" & tableDef.Name & "]"
            End If
        Next
    End With
End Sub

Public Sub RemoveWorkaroundForCorruptedQueryIssue()
    On Error Resume Next

    With CurrentDb
        Dim tableDef As tableDef
        For Each tableDef In .tableDefs
            Dim isSystemTable As Boolean
            isSystemTable = tableDef.Attributes And dbSystemObject

            If EndsWith(tableDef.Name, WorkaroundTableSuffix) And Not isSystemTable Then
                Dim originalTableName As String
                originalTableName = Left(tableDef.Name, Len(tableDef.Name) - Len(WorkaroundTableSuffix))

                Dim workaroundTableName As String
                workaroundTableName = tableDef.Name

                Call .QueryDefs.Delete(originalTableName)
                tableDef.Name = originalTableName

                Debug.Print "OldTableName" & vbTab & "[" & workaroundTableName & "]" & vbTab & _
                            "NewTableName" & vbTab & "[" & tableDef.Name & "]" & vbTab & "(Query deleted)"
            End If
        Next
    End With
End Sub

'From https://excelrevisited.blogspot.com/2012/06/endswith.html
Private Function EndsWith(str As String, ending As String) As Boolean
     Dim endingLen As Integer
     endingLen = Len(ending)
     EndsWith = (Right(Trim(UCase(str)), endingLen) = UCase(ending))
End Function

GitHub 리포지토리 에서 최신 코드를 찾을 수 있습니다 .

AddWorkaroundForCorruptedQueryIssue()_Table모든 비 시스템 테이블에 접미사 를 추가합니다 . 예를 들어 테이블의 IceCreams이름이IceCreams_Table .

또한 원래 테이블 이름을 사용하여 새 쿼리를 작성하여 이름이 바뀐 테이블의 모든 열을 선택합니다. 이 예에서 쿼리 이름이 지정 IceCreams되고 SQL이 실행 select * from [IceCreams_Table]됩니다.

RemoveWorkaroundForCorruptedQueryIssue() 역 동작을 수행합니다.

SQL Server와 같은 외부 비 MDB 테이블을 포함하여 모든 종류의 테이블에서 이것을 테스트했습니다. 그러나 테이블 대신 쿼리를 사용하면 특히 테이블을 사용한 원래 쿼리의 품질이 떨어지거나 매우 복잡한 경우 특정 경우 백엔드 데이터베이스에 대해 최적화되지 않은 쿼리가 실행될 수 있습니다.

(물론 코딩 스타일에 따라 응용 프로그램에서 문제가 발생할 수도 있습니다. 따라서 수정 프로그램이 일반적으로 적합한 지 확인한 후에는 모든 개체를 텍스트로 내보내고 찾기 바꾸기를 사용하는 것은 결코 나쁜 생각이 아닙니다 사용되는 테이블 이름이 테이블이 아닌 쿼리에 대해 실행되도록하는 마술.)

필자의 경우이 수정은 부작용없이 크게 작동합니다 . 과거에 만들 때 시스템 테이블로 표시하지 않았기 때문에 수동으로 이름을 USysRibbons_Table다시 USysRibbons바꾸어야했습니다.


나는 당신이 시스템 테이블을 결정하고 TableDef.Attributes그것을 내 대답에 복사하는 것을 좋아한다.) 실행 취소 기능은 좋은 생각이다. 일부 다른 부분에 결함이 있습니다 (예 : 테이블은 접미사로 끝나거나 newname이 이미 사용 중이거나 On Error Resume Next나중에 오류를 처리하지 않고). RubberduckVBA 를 알고 있습니까? 이 애드 인은 코드를 검사하고 다른 모든 기능 외에도 개선을위한 훌륭한 제안을합니다.
ComputerVersteher

그리고 당신은 우리의 접근 방식은 일으킬 수있는 버그를 표시해야한다 (참조 @Erics 내 대답에 코멘트)
ComputerVersteher

아, 나는 여기에 이미 비슷한 대답이 있다는 것을 보지 못 했으므로 검토해 주셔서 감사합니다! 접미사는 자체 상수로 정의되므로 이미 접미사를 사용하는 기존 객체가 정의되어있는 경우 쉽게 변경할 수 있습니다. 그렇지 않으면 스크립트는 그대로 작동하지만 누구나 각자의 필요에 맞게 스크립트를 수정하도록 권장해야합니다. 이 스크립트는 외부 / 연결된 테이블을 포함하여 다른 외부 데이터베이스 소스에 포함 된 상당히 큰 프로젝트 (400+ 테이블)에서 테스트되었습니다. Rubberduck에 대해서는 몰랐습니다 (MZ-Tools에 대해서만). 나는 확실히 그들을 확인합니다!
lauxjpn 2018

3

PowerShell을 통해이 프로세스를 자동화 하려는 경우 도움이 될만한 몇 가지 링크가 있습니다.

문제가있는 업데이트 검색 및 제거

https://www.arcath.net/2017/09/office-update-remover 에서 사용할 수있는 PowerShell 스크립트가 있습니다.이 스크립트 는 레지스트리에서 특정 Office 업데이트 (kb 번호로 전달)를 검색하고 다음을 호출하여 제거합니다. msiexec.exe. 이 스크립트는 레지스트리 키에서 두 GUID를 구문 분석하여 적절한 업데이트를 제거하는 명령을 빌드합니다.

KB4011626 및 기타 Office 업데이트 제거 방법 (추가 참조 : https://docs.microsoft.com/en-us/windows/win32/msi/uninstalling-patches )에 /REBOOT=REALLYSUPPRESS설명 된대로를 사용하는 것이 좋습니다 . 빌드하는 명령 행은 다음과 같습니다.

msiexec /i {90160000-0011-0000-0000-0000000FF1CE} MSIPATCHREMOVE={9894BF35-19C1-4C89-A683-D40E94D08C77} /qn REBOOT=REALLYSUPPRESS

스크립트를 실행하는 명령은 다음과 같습니다.

OfficeUpdateRemover.ps1 -kb 4484127

업데이트 설치 방지

여기서 권장되는 방법 은 업데이트를 숨기고있는 것 같습니다 . 분명히이 작업은 수동으로 수행 할 수 있지만 자동화에 도움이되는 일부 PowerShell 스크립트가 있습니다. 이 링크 : https://www.maketecheasier.com/hide-updates-in-windows-10/ 에 프로세스가 자세히 설명되어 있지만 여기에 요약하겠습니다.

  1. Windows Update PowerShell 모듈을 설치하십시오 .
  2. KB 번호로 업데이트를 숨기려면 다음 명령을 사용하십시오.

    Hide-WUUpdate -KBArticleID KB4484127

바라건대 이것은 다른 누군가에게 도움이 될 것입니다.


3

MS- 해결 방법을위한 VBA 스크립트 :

적어도 MSI 버전의 경우 가능한 경우 버그 코드 업데이트를 제거하는 것이 좋습니다 (내 코드를 시도하지 않는 경우). 답변을 참조 하십시오 https://stackoverflow.com/a/58833831/9439330 .

CTR (Click-To-Run) 버전의 경우 모든 Office 11- 업데이트를 제거해야합니다. 이로 인해 심각한 보안 문제가 발생할 수 있습니다 (중요 수정 사항이 제거되는지 확실하지 않음).

@Eric의 의견에서 :

  • Table.Tablename양식을 바인드 하는 데 사용 하는 경우 이전 table-name이 이제 query-name!이므로 바인드되지 않습니다.
  • OpenRecordSet(FormerTableNowAQuery, dbOpenTable) 실패합니다 (더 이상 테이블이 아닌 쿼리로)

주의! Office 2013 x86 CTR의 Northwind.accdb 에 대해 빠른 테스트를 마쳤습니다 .

Private Sub RenameTablesAndCreateQueryDefs()
With CurrentDb
    Dim tdf As DAO.TableDef
    For Each tdf In .TableDefs

        Dim oldName As String
        oldName = tdf.Name

        If Not (tdf.Attributes And dbSystemObject) Then 'credit to @lauxjpn for better check for system-tables
            Dim AllFields As String
            AllFields = vbNullString

            Dim fld As DAO.Field

            For Each fld In tdf.Fields
                AllFields = AllFields & "[" & fld.Name & "], "
            Next fld

            AllFields = Left(AllFields, Len(AllFields) - 2)
            Dim newName As String
            newName = oldName

            On Error Resume Next
            Do
                Err.Clear
                newName = newName & "_"
                tdf.Name = newName
            Loop While Err.Number = 3012
            On Error GoTo 0

            Dim qdf As DAO.QueryDef

            Set qdf = .CreateQueryDef(oldName)
            qdf.SQL = "SELECT " & AllFields & " FROM [" & newName & "]"
        End If
    Next
    .TableDefs.Refresh

End With
End Sub

시험용:

Private Sub TestError()
With CurrentDb
    .Execute "Update customers Set City = 'a' Where 1=1", dbFailOnError 'works

    .Execute "Update customers_ Set City = 'b' Where 1=1", dbFailOnError 'fails
End With
End Sub

4
이 해결 방법은 테이블에 바인딩 된 하위 폼 (쿼리에 리바운드해야 함)과 하드 코딩 된 테이블 이름으로 tabledef를 사용하는 코드를 망칠 수 있습니다. 주의해서 사용하면 응용 프로그램이 수행하는 작업에 따라 두 가지 새로운 버그를 만들기 위해 하나의 버그 만 수정됩니다.
Erik A

@ErikA 물론 해결 방법 만 있지만 문제없이 테이블에 형식으로 바인딩 Inventory to reorder Subform for Home할 수 있습니다. 심지어 테이블 대신 쿼리에 폼을 바인딩하는 것이 좋습니다 ( ? 와 같은 테이블에 바인딩되지 않음 ). InventoryHomeSelect * From table
ComputerVersteher

2
하위 폼을 테이블에 바인딩하면 일반적으로 Table.TableName표기법을 사용하여 수행합니다 . 당신이 할 경우 SELECT * FROM TableName대신, 당신은 물론 벌금입니다. Table.TableName그러나을 사용 하면 테이블 이름을 바꾸면 하위 폼이 바인딩되지 않습니다.
Erik A

@ErikA : 맞습니다. 그렇게하면 어떤 이점이 있습니까?
ComputerVersteher

3
더 짧은 것을 제외하고는 내가 아는 한. TableDefs!MyTableName.OpenRecordset(dbOpenTable)그래도 (인덱스 검색 지원)의 실질적인 이점이 있습니다.이 방법은 사용하는 경향이 있으며 접근 방식에 오류가 발생할 수도 있습니다.
Erik A

2

나는 대체 currentDb.ExecuteDocmd.RunSQL도우미 기능. 업데이트 문에 테이블이 하나만 포함되어 있으면 SQL 문을 사전 처리하고 변경할 수 있습니다. 나는 이미 dual(단일 행, 단일 열) 테이블을 가지고 있으므로 fakeTable 옵션을 사용했습니다.

참고 : 쿼리 개체는 변경되지 않습니다. VBA를 통한 SQL 실행에만 도움이됩니다.If you would like to change your query objects, use FnQueryReplaceSingleTableUpdateStatements and update your sql in each of your querydefs. Shouldn't be a problem either.

이것은 단지 개념 (If it's a single table update modify the sql before execution)이다. 필요에 따라 조정하십시오. 이 방법은 각 테이블에 대한 대체 쿼리를 생성하지 않습니다 (가장 쉬운 방법이지만 자체 단점이 있습니다 (예 : 성능 문제)).

+ 포인트 : MS가 버그를 수정 한 후에도이 도우미를 계속 사용할 수 있습니다 . 미래에 또 다른 문제가 발생하면 pre-process한 곳에서 SQL 을 사용할 수 있습니다. 나는 가지 않았다관리자 액세스 권한이 필요하기 때문에 업데이트 방법 제거 모든 버전을 올바른 버전으로 가져 오는 데 너무 오래 걸리고 + 제거하더라도 일부 최종 사용자의 그룹 정책은 최신 업데이트를 다시 설치합니다. 같은 문제로 돌아 왔습니다.

소스 코드에 액세스 할 수있는 경우 use this method 최종 사용자에게 문제가 없음을 100 % 확신하는 경우

Public Function Execute(Query As String, Optional Options As Variant)
    'Direct replacement for currentDb.Execute

    If IsBlank(Query) Then Exit Function

    'invalid db options remove
    If Not IsMissing(Options) Then
        If (Options = True) Then
            'DoCmd RunSql query,True ' True should fail so transactions can be reverted
            'We are only doing this so DoCmd.RunSQL query, true can be directly replaced by helper.Execute query, true.
            Options = dbFailOnError
        End If
    End If

    'Preprocessing the sql command to remove single table updates
    Query = FnQueryReplaceSingleTableUpdateStatements(Query)

    'Execute the command
    If ((Not IsMissing(Options)) And (CLng(Options) > 0)) Then
        currentDb.Execute Query, Options
    Else
        currentDb.Execute Query
    End If

End Function

Public Function FnQueryReplaceSingleTableUpdateStatements(Query As String) As String
    ' ON November 2019 Microsoft released a buggy security update that affected single table updates.
    '/programming/58832269/getting-error-3340-query-is-corrupt-while-executing-queries-docmd-runsql

    Dim singleTableUpdate   As String
    Dim tableName           As String

    Const updateWord        As String = "update"
    Const setWord           As String = "set"

    If IsBlank(Query) Then Exit Function

    'Find the update statement between UPDATE ... SET
    singleTableUpdate = FnQueryContainsSingleTableUpdate(Query)

    'do we have any match? if any match found, that needs to be preprocessed
    If Not (IsBlank(singleTableUpdate)) Then

        'Remove UPDATe keyword
        If (VBA.Left(singleTableUpdate, Len(updateWord)) = updateWord) Then
            tableName = VBA.Right(singleTableUpdate, Len(singleTableUpdate) - Len(updateWord))
        End If

        'Remove SET keyword
        If (VBA.Right(tableName, Len(setWord)) = setWord) Then
            tableName = VBA.Left(tableName, Len(tableName) - Len(setWord))
        End If

        'Decide which method you want to go for. SingleRow table or Select?
        'I'm going with a fake/dual table.
        'If you are going with update (select * from T) as T, make sure table aliases are correctly assigned.
        tableName = gDll.sFormat("UPDATE {0},{1} SET ", tableName, ModTableNames.FakeTableName)

        'replace the query with the new statement
        Query = vba.Replace(Query, singleTableUpdate, tableName, compare:=vbDatabaseCompare, Count:=1)

    End If

    FnQueryReplaceSingleTableUpdateStatements = Query

End Function

Public Function FnQueryContainsSingleTableUpdate(Query As String) As String
    'Returns the update ... SET statment if it contains only one table.

    FnQueryContainsSingleTableUpdate = ""
    If IsBlank(Query) Then Exit Function

    Dim pattern     As String
    Dim firstMatch  As String

    'Get the pattern from your settings repository or hardcode it.
    pattern = "(update)+(\w|\s(?!join))*set"

    FnQueryContainsSingleTableUpdate = FN_REGEX_GET_FIRST_MATCH(Query, pattern, isGlobal:=True, isMultiline:=True, doIgnoreCase:=True)

End Function

Public Function FN_REGEX_GET_FIRST_MATCH(iText As String, iPattern As String, Optional isGlobal As Boolean = True, Optional isMultiline As Boolean = True, Optional doIgnoreCase As Boolean = True) As String
'Returns first match or ""

    If IsBlank(iText) Then Exit Function
    If IsBlank(iPattern) Then Exit Function

    Dim objRegex    As Object
    Dim allMatches  As Variant
    Dim I           As Long

    FN_REGEX_GET_FIRST_MATCH = ""

   On Error GoTo FN_REGEX_GET_FIRST_MATCH_Error

    Set objRegex = CreateObject("vbscript.regexp")
    With objRegex
        .Multiline = isMultiline
        .Global = isGlobal
        .IgnoreCase = doIgnoreCase
        .pattern = iPattern

        If .test(iText) Then
            Set allMatches = .Execute(iText)
            If allMatches.Count > 0 Then
                FN_REGEX_GET_FIRST_MATCH = allMatches.item(0)
            End If
        End If
    End With

    Set objRegex = Nothing

   On Error GoTo 0
   Exit Function

FN_REGEX_GET_FIRST_MATCH_Error:
    FN_REGEX_GET_FIRST_MATCH = ""

End Function

지금은 CTRL +F

검색 및 교체 docmd.RunSQL 와 함께helper.Execute

검색 및 교체 [currentdb|dbengine|or your dbobject].execute 와 함께helper.execute

재미 있어요!


0

이 버그가 수정 되었음에도 최종 사용자가 업데이트 할 수없는 다양한 기업을 통해이 수정 사항이 아직 완전히 채워지지 않았습니다.

에 대한 해결 방법은 다음과 같습니다 DoCmd.RunSQL "UPDATE users SET uname= 'bob' WHERE usercode=1". 문제가되는 쿼리를 주석 처리하고 아래 코드를 삭제하십시오.

    'DoCmd.RunSQL "UPDATE users SET uname= 'bob' WHERE usercode=1"
    Dim rst As DAO.Recordset
    Set rst = CurrentDb.OpenRecordset("users")
    rst.MoveLast
    rst.MoveFirst
    rst.FindFirst "[usercode] = 1" 'note: if field is text, use "[usercode] = '1'"
    rst.Edit
    rst![uname] = "bob"
    rst.Update
    rst.Close
    Set rst = Nothing

예쁘다고 말할 수는 없지만 작업이 완료됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.