Отримання помилки 3340 Запит "" пошкоджений під час виконання запитів DoCmd.RunSQL


83

Після встановлення оновлення Windows для Office 2010, що вирішує KB 4484127, я отримую помилку під час виконання запитів, які містять пункт WHERE.

Наприклад, виконуючи цей запит:

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

Результати цієї помилки:

Номер помилки = 3340 Запит "" пошкоджений

Наразі актуальне оновлення все ще встановлено:

Знімок екрана із оновленням 448127 оновленого пакета оновлень 2 для Microsoft Office 2010

Як я можу успішно виконувати запити? Чи слід просто видалити це оновлення?

Відповіді:


92

Підсумок

Це відома помилка, викликана оновленнями Office, опублікованими 12 листопада 2019. Помилка впливає на всі версії Access, які зараз підтримуються Microsoft (від Access 2010 до 365).

Цю помилку виправлено.

  • Якщо ви використовуєте версію Office C2R ("Клацніть для запуску"), використовуйте "Оновити зараз" :
    • Доступ 2010 C2R: виправлено в збірці 7243.5000
    • Доступ 2013 C2R: виправлено в збірці 5197.1000
    • Доступ 2016 C2R: виправлено в збірці 12130.20390
    • Доступ 2019 (v1910): виправлено в збірці 12130.20390
    • Доступ 2019 (об'ємна ліцензія): зафіксовано в збірці 10353.20037
    • Щомісячний канал Office 365: виправлено в збірці 12130.20390
    • Office 365 напівроку: виправлено у збірці 11328.20480
    • Служба 365 на півріччя продовжена: виправлено в збірці 10730.20422
    • Піврічний цільовий офіс 365: зафіксовано в збірці 11929.20494
  • Якщо ви використовуєте версію Office Office MSI, встановіть оновлення, яке відповідає вашій версії Office. Усі ці виправлення випущені в Microsoft Update, тому для встановлення всіх оновлених оновлень Windows має бути достатньо:
    • Доступ 2010 MSI: зафіксовано в KB4484193
    • Доступ 2013 MSI: зафіксовано в KB4484186
    • Доступ до MSI 2016: виправлено у KB4484180

Приклад

Ось мінімальний приклад докори:

  1. Створіть нову базу даних Access.
  2. Створіть нову порожню таблицю "Таблиця1" із полем ідентифікатора за замовчуванням та довгим полем "Мінт".
  3. Виконайте наступний код у негайному вікні редактора VBA:

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

Очікуваний результат : Заява успішно завершується.

Фактичний результат, коли встановлено одне з оновлених помилок: виникає помилка 3340 під час виконання ("Запит" пошкоджений).


Пов’язані посилання:


9
Здається, ця публікація стикається з тією ж помилкою, використовуючи 64-розрядний режим доступу та OLEDB. Страшні речі, це зробить багато додатків, які використовують Access для зберігання даних, невикористаними.
Ерік

4
Я щойно перевірив систему з 32-розрядною версією Office 2013 і на цьому конкретному апараті UUID для оновлення 90150000-006E-0409-0000-0000000FF1CE... це -0409-, ні -0407-.
Горд Томпсон

4
Я щойно перевірив ще одну машину в офісі, в якій є Office 2013 64-розрядна, і UUID також є -006E-0409-. На обох машинах встановлений пакет оновлень 1 для Microsoft Office 2013 (KB2850036).
Горд Томпсон

4
Для Office 2010 Pro Plus (SP2) нам потрібно було користуватися {90140000-0011-0000-0000-0000000FF1CE}в пакетному сценарії. Примітка {9014...ні{9114..}
AdamsTips

2
Я вирішив вирішення проблеми, але я все ще отримую помилку. Хтось ще мав цю проблему?
користувач218076

33

Найпростіше рішення

Для моїх користувачів чекати майже місяць до 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, а проблема, яка була представлена ​​з версією Office Patch Tuesday Office. Зміна виправлення вразливості безпеки призводить до того, що деякі законні запити повідомляються про пошкоджені. Оскільки зміна є виправленням безпеки, вона впливає на ВСІ складання Office, включаючи 2010, 2013, 2016, 2019 та O365.

Помилка була виправлена ​​у всіх каналах, але час доставки залежатиме від того, на якому каналі ви перебуваєте.

На 2010, 2013 та 2016 рік, набудовані ліцензії MSI, 2019 та обсяги ліцензій на обсяг та піврічний канал O365, виправлення буде встановлено у грудні в грудні Patch Tuesday, 10 грудня. Для O365, щомісячного каналу та інсайдерів це буде встановлено коли буде випущена Жовтнева вилка, запланована на 24 листопада

Для телеканалу "Semi-Year" помилка була введена в 11328.20468, яка вийшла 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
Ви насправді говорите прямим обличчям, що ми переходимо до 100 тисяч тисяч рядків коду, розгорнутих у декількох додатках, і виправляємо всі оновлення sql, які просто оновлюють ряд даних? Я припускаю, що якщо ви пишете новий запит сьогодні, і саме зараз, такий спосіб вирішення можливий. Але для існуючого коду та застосувань ідея, що оновлення sql потрібно змінити, звичайно, не є практичним підходом до вирішення проблем будь-яким можливим способом.
Альберт Д. Каллал

5
@ AlbertD.Kallal, вам слід знати зі списку MVP, що я просто посилаюся на пояснення до джерела проблеми. Як вирішити проблему, насправді залежить від вас і що може відповідати вашому сценарію. Описаний тут метод - лише один із кількох.
Густав

1
@ AlbertD.Kallal Не слід виправляти таблиці та створювати QueryDefs зі старим іменем таблиці? (Я
ComputerVersteher

Ви можете зробити це без програмування, наприклад, перейменувати таблицю "користувачів" на "userst", а потім створити ім'я запиту "users" - і тоді воно буде працювати без програми програмування.
Zvi

9
@ AlbertD.Kallal: Я поділяю ваш біль - якщо це помилка, що впливає на бібліотеку виконання VC, я не думаю, що MS затримає виправлення на один місяць і запропонує вирішити "переписати, перекомпілювати та переукласти". (Справедливо кажучи, вони виправили та випустили випуск VBA в кінці серпня швидко.) Але давайте не зніматимемо месенджера - Густав, здається, не є співробітником MS. Будемо сподіватися, що вони переглянуть і випустять виправлення раніше; Зрештою, це також впливає на програми, написані іншими мовами, які просто трапляються з використанням механізму доступу DB .
Хайнзі

15

Щоб тимчасово вирішити цю проблему, залежить від використовуваної версії Access:
Оновлення Access 2010 Uninstall KB4484127
Access 2013 Видалення оновлення KB4484119
Access 2016 Видалення оновлення KB4484113
Access 2019 АКО ЗАПИТАНО (tbc). Перехід від версії 1808 (збірка 10352.20042) до версії 1808 (збірка 10351.20054)
Office 365 ProPlus Пониження версії з версії 1910 (збірка 12130.20344) до попередньої збірки, див. Https://support.microsoft.com/en-gb/help/2770432/ як повернути-до-попередньої-версії-офісу-2013-або-офісу-2016-кліки


Я видалив його, але він знову встановився наступного разу, коли запустив Windows. Як запобігти перевстановці?
dsteele

5
@dsteele Якщо версія MSI та WSUS не використовується, використовуйте support.microsoft.com/en-us/help/3073930/… інструмент усунення несправностей. На CTR вимкніть оновлення в налаштуваннях Office-Account ..
ComputerVersteher

5

Ми з нашими клієнтами боролися з цим останні два дні і, нарешті, написали документ, щоб детально обговорити це питання разом із деякими рішеннями: http://fmsinc.com/MicrosoftAccess/Errors/query_is_corrupt/

Він включає наші висновки про те, що це впливає на рішення Access під час запуску запитів оновлення на локальних таблицях, пов'язаних таблицях Access і навіть пов'язаних таблиць SQL Server.

Це також впливає на рішення, що не стосуються Microsoft Access, використовуючи двигун бази даних Access (ACE) для підключення до баз даних Access за допомогою ADO. Це включає додатки Visual Studio (WinForm), додатки VB6 і навіть веб-сайти, що оновлюють бази даних Access на машинах, на яких ніколи не було встановлено Access або Office.

Цей збій може вплинути навіть на програми Microsoft, які використовують ACE, такі як PowerBI, Power Query, SSMA тощо (не підтверджено), і звичайно, інші програми, такі як Excel, PowerPoint або Word, що використовують VBA для зміни баз даних Access.

На додаток до очевидного видалення неправомірних оновлень безпеки, ми також включаємо деякі варіанти, коли неможливо видалити через дозволи чи розповсюдження програм Access для зовнішніх клієнтів, чиї ПК поза вашим контролем. Це включає в себе зміну всіх запитів на оновлення та розповсюдження програм Access за допомогою Access 2007 (роздрібний або під час виконання), оскільки оновлення безпеки не впливає на цю версію.


4

Використовуйте наступний модуль для автоматичного впровадження запропонованого рішення Microsofts (використовуючи запит замість таблиці). В якості запобіжних заходів спершу створіть резервну копію бази даних.

Використовуйте, 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() чинить зворотні дії.

Я перевірив це з усіма типами таблиць, включаючи зовнішні таблиці, що не мають MDB (наприклад, SQL Server). Але майте на увазі, що використання запиту замість таблиці може призвести до неоптимізованих запитів, що виконуються із базовою базою даних у конкретних випадках, особливо якщо ваші оригінальні запити, які використовували таблиці, мають низьку якість або дуже складні.

(І звичайно, залежно від вашого стилю кодування, ви також можете порушити речі у вашій програмі. Тож після перевірки, що виправлення, як правило, працює на вас, ніколи не є поганою ідеєю експортувати всі ваші об’єкти як текст та використовувати замість пошуку магія забезпечити, що будь-які випадки використання імен таблиць будуть запущені проти запитів, а не таблиць.)

У моєму випадку, це виправлення працює в основному без будь - яких побічних ефектів, мені просто потрібно вручну перейменувати USysRibbons_Tableназад USysRibbons, так як я не помітив його як системну таблицю , коли я створив його в минулому.


Мені подобається, що ви визначаєте систематизовану систему TableDef.Attributesта скопіюйте її до моєї відповіді;) та функція скасування - це гарна ідея (але старе та нове ім’я потрібно зберігати в таблиці, залежно від відсутності таблиць із суфіксом перед перейменуванням). Деякі інші частини несправні (наприклад, таблиці можуть закінчуватися суфіксом, або нове ім'я вже використовується, або On Error Resume Nextпізніше не обробляти помилки). Ви знаєте RubberduckVBA ? Цей Addin може перевіряти ваш код та вносить приємні пропозиції щодо вдосконалення, крім усіх інших функцій.
ComputerVersteher

І вам слід вказати на помилки, які може спричинити наш підхід (Дивіться коментарі @Erics до моєї відповіді)
ComputerVersteher

Ах, я не бачив, що тут вже була схожа відповідь, тож дякую за відгук! Суфікс визначений у власній константі, тому його легко можна змінити, якщо вже є визначений об'єкт, який уже використовує суфікс. Інакше сценарій працює так, як є, але будь-хто повинен почувати себе заохоченим змінити його під свої індивідуальні потреби. Сценарій був протестований на досить великих проектах (400+ таблиць), включаючи зовнішні / пов'язані таблиці до різних зовнішніх джерел баз даних. Я не знав про Rubberduck (лише про MZ-Tools). Я обов'язково їх перевіряю!
lauxjpn

3

Для тих, хто прагне автоматизувати цей процес через PowerShell , ось декілька посилань, які я виявив, що може бути корисним:

Виявити та видалити інші оновлення

Тут доступний скрипт PowerShell https://www.arcath.net/2017/09/office-update-remover, який здійснює пошук у реєстрі для певного оновлення Office (передається як номер kb) та видаляє його за допомогою виклику до msiexec.exe. Цей скрипт розбирає обидва GUID з ключів реєстру для складання команди для видалення відповідного оновлення.

Я б запропонував зміни, /REBOOT=REALLYSUPPRESSяк описано в розділі Як видалити KB4011626 та інші оновлення Office (Додаткова посилання: https://docs.microsoft.com/en-us/windows/win32/msi/uninstalling-patches ). Командний рядок, який ви будуєте, виглядає приблизно так:

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 PowerShell .
  2. Використовуйте таку команду, щоб приховати оновлення за номером KB:

    Hide-WUUpdate -KBArticleID KB4484127

Сподіваємось, це допоможе комусь іншому там.


3

VBA-скрипт для MS-вирішення:

Рекомендується видалити оновлення помилок, якщо можливо (якщо не спробувати мій код), принаймні для версій MSI. Дивіться відповідь https://stackoverflow.com/a/58833831/9439330 .

Для версій CTR (натискання для запуску) потрібно видалити всі оновлення Office в листопаді, що може спричинити серйозні проблеми із безпекою (не впевнені, чи будуть усунені критичні виправлення).

З коментарів @ Еріка:

  • Якщо ви використовуєте Table.Tablenameдля прив'язки форм, вони стають незв’язаними, оскільки колишня назва таблиці тепер є ім'ям запиту !.
  • OpenRecordSet(FormerTableNowAQuery, dbOpenTable) не вдасться (як його запит зараз, а не таблиця більше)

Обережно! Просто швидкий тест на Northwind.accdb на Office 2013 x86 CTR без гарантії!

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
Зауважте, що це вирішення призведе до руйнування підформ, пов'язаних з таблицями (потрібно буде відновлюватись на запити) та коду, що працює з tabledefs з твердою кодовою назвою таблиці. Використовуйте з великою обережністю, шанси - це виправлення однієї помилки лише для створення двох нових, залежно від того, що робить ваша програма.
Ерік А

@ErikA Звичайно, лише обхід, але я можу прив’язати Inventory to reorder Subform for Homeдо Inventoryтаблиці Homeформу, без проблем. Навіть не рекомендується прив’язувати форми до запитів замість таблиць (не прив’язує до таблиці, як Select * From table?).
ComputerVersteher

2
Якщо я прив'язую підформу до таблиці, я зазвичай це роблю, використовуючи Table.TableNameпозначення. Якщо ви робите SELECT * FROM TableNameзамість цього, ви, звичайно, добре. Але якщо ви використовуєте Table.TableName, ваша підформа буде неприєднаною, якщо перейменувати таблицю.
Ерік

@ErikA: Це правда. Якась вигода, роблячи це?
ComputerVersteher

3
Наскільки я не знаю, за винятком того, що це коротше. Однак є суттєва перевага TableDefs!MyTableName.OpenRecordset(dbOpenTable)(підтримка пошуку індексу), яку я також схильний використовувати і також спричинить помилки при вашому підході
Ерік,

2

Я замінив функцію currentDb.Executeі Docmd.RunSQLпомічник. Це може попередньо обробити та змінити оператор SQL, якщо будь-який оператор оновлення містить лише одну таблицю. У мене вже є dualтаблиця (один рядок, один стовпець), тому я пішов з опцією fakeTable.

Примітка . Це не змінить ваші об’єкти запиту. Це допоможе лише виконанню SQL через VBA.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

Я не можу сказати, що це красиво, але це робить роботу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.