[vba] 쿼리 실행 중 오류 3340 ”쿼리가 손상되었습니다. DoCmd.RunSQL

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

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

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

이 오류가 발생합니다 :

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

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

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

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



답변

요약

이 버그는 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이 발생합니다 ( “쿼리 ”이 손상되었습니다”).


관련된 링크들:


답변

가장 간단한 솔루션

내 사용자에게는 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);  

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


답변

이것은 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);

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


답변

이 문제를 일시적으로 해결하려면 사용중인 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의 이전 버전으로 되 돌리는 방법


답변

우리와 고객은 지난 이틀 동안이 문제로 어려움을 겪고 마지막으로 몇 가지 솔루션과 함께 문제에 대해 자세히 논의하기위한 논문을 작성했습니다. 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 응용 프로그램 배포가 포함됩니다.


답변

다음 모듈을 사용하여 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바꾸어야했습니다.


답변

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

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