Obteniendo Error 3340 Query '' está dañado al ejecutar consultas DoCmd.RunSQL

83

Desde que instalé la actualización de Windows para Office 2010 resolviendo KB 4484127 , recibo un error al ejecutar consultas que contienen una cláusula WHERE.

Por ejemplo, ejecutando esta consulta:

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

Resultados en este error:

Número de error = 3340 La consulta '' está corrupta

La actualización en cuestión todavía está instalada actualmente:

Captura de pantalla que muestra la actualización 448127 de Microsoft Office 2010 Service Pack 2

¿Cómo puedo ejecutar con éxito mis consultas? ¿Debo desinstalar esta actualización?

Zvi Redler
fuente

Respuestas:

92

Resumen

Este es un error conocido causado por las actualizaciones de Office lanzadas el 12 de noviembre de 2019. El error afecta a todas las versiones de Access actualmente compatibles con Microsoft (desde Access 2010 hasta 365).

Este error se ha corregido.

  • Si usa una versión C2R (Hacer clic y ejecutar) de Office, use "Actualizar ahora" :
    • Access 2010 C2R: corregido en Build 7243.5000
    • Access 2013 C2R: corregido en Build 5197.1000
    • Access 2016 C2R: corregido en Build 12130.20390
    • Acceso 2019 (v1910): corregido en la compilación 12130.20390
    • Access 2019 (Licencia por volumen): corregido en Build 10353.20037
    • Canal mensual de Office 365: corregido en la compilación 12130.20390
    • Office 365 semestral: corregido en la compilación 11328.20480
    • Office 365 semestral extendido: corregido en Build 10730.20422
    • Office 365 semestral dirigido: corregido en la compilación 11929.20494
  • Si usa una versión MSI de Office, instale la actualización que coincida con su versión de Office. Todos estos parches se han lanzado en Microsoft Update, por lo que debería ser suficiente instalar todas las actualizaciones de Windows pendientes :

Ejemplo

Aquí hay un ejemplo de reproducción mínima:

  1. Cree una nueva base de datos de Access.
  2. Cree una nueva tabla vacía "Tabla1" con el campo ID predeterminado y un campo Entero largo "myint".
  3. Ejecute el siguiente código en la ventana Inmediato del editor de VBA:

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

Resultado esperado : la declaración finaliza correctamente.

Resultado real con una de las actualizaciones de errores instaladas: se produce el error 3340 en tiempo de ejecución ("La consulta 'está dañada").


Enlaces relacionados:

Heinzi
fuente
99
Esta publicación parece encontrar el mismo error al usar el tiempo de ejecución de Access de 64 bits y OLEDB. Miedo, esto hará que muchas aplicaciones que usan Access para almacenar datos sean inutilizables.
Erik A
44
Acabo de comprobar un sistema con Office 2013 de 32 bits y en esa máquina en particular, el UUID para la actualización es 90150000-006E-0409-0000-0000000FF1CE... eso -0409-no -0407-.
Gord Thompson el
44
Acabo de comprobar otra máquina en la oficina que tiene Office 2013 de 64 bits y el UUID -006E-0409-también. Ambas máquinas tienen instalado el Service Pack 1 para Microsoft Office 2013 (KB2850036).
Gord Thompson el
44
Para Office 2010 Pro Plus (SP2) necesitábamos usarlo {90140000-0011-0000-0000-0000000FF1CE}en el script por lotes. Nota {9014...no{9114..}
AdamsTips
2
He parcheado la actualización oficial para resolver el problema, pero aún recibo el error. ¿Alguien más tiene ese problema?
user218076
33

La solución más simple

Para mis usuarios, esperar casi un mes hasta el 10 de diciembre para una versión de reparación de Microsoft no es una opción. Tampoco está desinstalando la actualización ofensiva de Microsoft en varias estaciones de trabajo bloqueadas por el gobierno.

Necesito aplicar una solución alternativa, pero no estoy exactamente entusiasmado con lo que sugirió Microsoft: crear y sustituir una consulta para cada tabla.

La solución es reemplazar el nombre de la tabla con una (SELECT * FROM Table)consulta simple directamente en el UPDATEcomando. Esto no requiere crear y guardar un montón de consultas, tablas o funciones adicionales.

EJEMPLO:

Antes de:

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

Después:

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

Eso debería ser mucho más fácil de implementar en varias bases de datos y aplicaciones (y en una reversión posterior).

Joe Marinucci
fuente
20

Este no es un problema de actualización de Windows, sino un problema que se introdujo con la versión de noviembre de Patch Tuesday Office. Un cambio para corregir una vulnerabilidad de seguridad hace que algunas consultas legítimas se denuncien como corruptas. Debido a que el cambio fue una solución de seguridad, afecta TODAS las compilaciones de Office, incluidas 2010, 2013, 2016, 2019 y O365.

El error se ha corregido en todos los canales, pero el momento de la entrega dependerá de en qué canal se encuentre.

Para 2010, 2013 y 2016 MSI, y las compilaciones de licencias por volumen de 2019, y el canal semestral O365, la corrección se realizará en la versión Martes de parche de diciembre, 10 de diciembre. Para O365, Canal mensual e Insiders, esto se solucionará cuando se lanza la bifurcación de octubre, actualmente planificada para el 24 de noviembre.

Para el canal semianual, el error se introdujo en 11328.20468, que se lanzó el 12 de noviembre, pero no se implementa a todos a la vez. Si puede, es posible que desee retrasar la actualización hasta el 10 de diciembre.

El problema ocurre para las consultas de actualización en una sola tabla con un criterio especificado (por lo que otros tipos de consultas no deberían verse afectados, ni ninguna consulta que actualice todas las filas de una tabla, ni una consulta que actualice el conjunto de resultados de otra consulta). Dado eso, la solución más simple en la mayoría de los casos es cambiar la consulta de actualización para actualizar otra consulta que seleccione todo de la tabla, en lugar de actualizar la consulta directamente.

Es decir, si tiene una consulta como:

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

Luego, cree una nueva consulta (Consulta1) definida como:

Select * from Table1;

y actualice su consulta original a:

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

Página oficial: Error de acceso: "La consulta está dañada"

Gustav
fuente
13
¿Estás diciendo con franqueza que vamos a cientos de miles de líneas de código implementadas en múltiples aplicaciones y arreglamos todas las actualizaciones de SQL que simplemente actualizan una fila de datos? Supongo que si escribe una nueva consulta hoy, y ahora mismo, entonces es posible tal solución. Pero, para el código y las aplicaciones existentes, la idea de que las actualizaciones de SQL sean cambiadas no es, por supuesto, un enfoque práctico para la resolución de problemas de ninguna manera posible.
Albert D. Kallal el
55
@ AlbertD.Kallal, debe saber por la lista de MVP, que solo me refiero a la explicación de la fuente del problema. Cómo lidiar con el problema depende realmente de usted y de lo que puede ajustarse a su escenario. El método descrito aquí es solo uno de varios.
Gustav
1
@ AlbertD.Kallal ¿No debería cambiar el nombre de las tablas y crear QueryDefs con el nombre de la tabla anterior? (
ComputerVersteher
Puede hacerlo sin programación, por ejemplo, cambiar el nombre de la tabla "usuarios" a "userst" y luego crear el nombre de consulta "usuarios", y luego funcionará sin ningún tipo de programación ....
Zvi Redler
99
@ AlbertD.Kallal: Comparto su dolor: si esto fuera un error que afectara a la biblioteca de tiempo de ejecución de VC, no creo que MS demore la reparación por un mes y sugiera una solución alternativa de "reescribir, recompilar y volver a implementar". (Para ser justos, arreglaron y publicaron el problema de VBA a fines de agosto rápidamente.) Pero no disparemos al mensajero: Gustav no parece ser un empleado de MS. Esperemos que reconsideren y publiquen un parche antes; después de todo, también afecta a las aplicaciones escritas en otros idiomas que simplemente usan el motor de Access DB .
Heinzi
15

Para resolver este problema temporalmente depende de la versión de Access en uso:
Access 2010 Desinstalar la actualización KB4484127
Access 2013 Desinstalar la actualización KB4484119
Access 2016 Desinstalar la actualización KB4484113
Access 2019 SI SE REQUIERE (por confirmar). Descenso de la versión 1808 (compilación 10352.20042) a la versión 1808 (compilación 10351.20054)
Office 365 ProPlus Descenso de la versión 1910 (compilación 12130.20344) a una compilación anterior, consulte https://support.microsoft.com/en-gb/help/2770432/ cómo-revertir-a-una-versión-anterior-de-office-2013-u-office-2016-clic

Conceder
fuente
Lo desinstalé, pero se volvió a instalar la próxima vez que inicie Windows. ¿Cómo evita que se reinstale?
dsteele
55
@dsteele Si la versión MSI y no WSUS, use support.microsoft.com/en-us/help/3073930/… herramienta de solución de problemas. En CTR, deshabilite las actualizaciones en Office-Account-Settings ..
ComputerVersteher
5

Nosotros y nuestros clientes hemos tenido problemas con esto en los últimos dos días y finalmente escribimos un documento para discutir el problema en detalle junto con algunas soluciones: http://fmsinc.com/MicrosoftAccess/Errors/query_is_corrupt/

Incluye nuestros hallazgos de que impacta las soluciones de Access cuando se ejecutan consultas de actualización en tablas locales, tablas de acceso vinculadas e incluso tablas vinculadas de SQL Server.

También afecta a las soluciones que no son de Microsoft Access que utilizan el Motor de base de datos de acceso (ACE) para conectarse a las bases de datos de Access mediante ADO. Eso incluye aplicaciones de Visual Studio (WinForm), aplicaciones VB6 e incluso sitios web que actualizan bases de datos de Access en máquinas que nunca tenían Access u Office instaladas en ellas.

Este bloqueo incluso puede afectar las aplicaciones de Microsoft que usan ACE como PowerBI, Power Query, SSMA, etc. (no confirmado) y, por supuesto, otros programas como Excel, PowerPoint o Word que usan VBA para modificar bases de datos de Access.

Además de la obvia desinstalación de las Actualizaciones de seguridad ofensivas, también incluimos algunas opciones cuando no es posible desinstalar debido a permisos o distribución de aplicaciones de Access a clientes externos cuyas PC están fuera de su control. Eso incluye cambiar todas las consultas de Actualización y distribuir las aplicaciones de Access usando Access 2007 (minorista o en tiempo de ejecución) ya que esa versión no se ve afectada por las actualizaciones de seguridad.

LukeChung-FMS
fuente
4

Use el siguiente módulo para implementar automáticamente la solución sugerida de Microsofts (usando una consulta en lugar de una tabla). Como precaución, primero haga una copia de seguridad de su base de datos.

Use AddWorkaroundForCorruptedQueryIssue()para agregar la solución alternativa y RemoveWorkaroundForCorruptedQueryIssue()para eliminarla en cualquier momento.

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

Puede encontrar el último código en mi repositorio de GitHub .

AddWorkaroundForCorruptedQueryIssue()agregará el sufijo _Tablea todas las tablas que no sean del sistema, por ejemplo, la tabla IceCreamsse renombrará a IceCreams_Table.

También creará una nueva consulta con el nombre de la tabla original, que seleccionará todas las columnas de la tabla renombrada. En nuestro ejemplo, la consulta se nombraría IceCreamsy ejecutaría el SQL select * from [IceCreams_Table].

RemoveWorkaroundForCorruptedQueryIssue() hace las acciones inversas.

Probé esto con todo tipo de tablas, incluidas las tablas externas que no son MDB (como SQL Server). Pero tenga en cuenta que el uso de una consulta en lugar de una tabla puede conducir a consultas no optimizadas que se ejecutan en una base de datos de back-end en casos específicos, especialmente si sus consultas originales que utilizaron las tablas son de baja calidad o muy complejas.

(Y, por supuesto, dependiendo de su estilo de codificación, también es posible romper cosas en su aplicación. Entonces, después de verificar que la solución generalmente funciona para usted, nunca es una mala idea exportar todos sus objetos como texto y usar algunos reemplazos de búsqueda magia para garantizar que cualquier aparición de nombres de tablas se ejecute en las consultas y no en las tablas).

En mi caso, esta solución funciona en gran medida, sin efectos secundarios, sólo tenía que cambiar manualmente el nombre USysRibbons_Tablede nuevo a USysRibbons, ya que no había marcado como una tabla del sistema cuando creé que en el pasado.

lauxjpn
fuente
Me gusta que determine una tabla del sistema con TableDef.Attributesy copie eso en mi respuesta;) y una función de deshacer es una buena idea (pero el nombre antiguo y el nuevo deben almacenarse en una tabla, ya que no dependen de tablas con sufijo antes del cambio de nombre). Algunas otras partes están defectuosas (por ejemplo, las tablas pueden terminar con el sufijo o newname ya está en uso o On Error Resume Nextsin errores de manejo más adelante). ¿Conoces RubberduckVBA ? Este complemento puede inspeccionar su código y hace buenas sugerencias para mejorar, además de todas las otras características.
ComputerVersteher
Y debe señalar los errores que puede causar nuestro enfoque (consulte los comentarios de @Erics sobre mi respuesta)
ComputerVersteher
Ah, no vi que ya hubiera una respuesta similar aquí, ¡así que gracias por la revisión! El sufijo se define en su propia constante, por lo que se puede cambiar fácilmente en caso de que haya un objeto ya existente definido que ya utilice el sufijo. De lo contrario, el script funciona como está, pero cualquiera debería sentirse animado a modificarlo según sus necesidades individuales. El script se ha probado en proyectos bastante grandes (más de 400 tablas) que incluyen tablas externas / vinculadas a diferentes fuentes de bases de datos externas. No sabía sobre Rubberduck (solo sobre MZ-Tools). ¡Definitivamente los revisaré!
lauxjpn
3

Para aquellos que buscan automatizar este proceso a través de PowerShell , aquí hay algunos enlaces que encontré que pueden ser útiles:

Detectar y eliminar las actualizaciones ofensivas

Hay una secuencia de comandos de PowerShell disponible aquí https://www.arcath.net/2017/09/office-update-remover que busca en el registro una actualización específica de Office (pasada como un número kb) y la elimina mediante una llamada a msiexec.exe. Este script analiza los dos GUID de las claves del registro para generar el comando para eliminar la actualización adecuada.

Un cambio que sugeriría sería usar el /REBOOT=REALLYSUPPRESSque se describe en Cómo desinstalar KB4011626 y otras actualizaciones de Office (Referencia adicional: https://docs.microsoft.com/en-us/windows/win32/msi/uninstalling-patches ). La línea de comando que está creando se ve así:

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

El comando para ejecutar el script se vería así:

OfficeUpdateRemover.ps1 -kb 4484127

Evitar que se instalen las actualizaciones

El enfoque recomendado aquí parece estar ocultando la actualización . Obviamente, esto se puede hacer manualmente, pero hay algunos scripts de PowerShell que pueden ayudar con la automatización. Este enlace: https://www.maketecheasier.com/hide-updates-in-windows-10/ describe el proceso en detalle, pero lo resumiré aquí.

  1. Instale el Módulo de Windows Update PowerShell .
  2. Use el siguiente comando para ocultar una actualización por número KB:

    Hide-WUUpdate -KBArticleID KB4484127

Esperemos que esto sea de ayuda para alguien más.

AdamsTips
fuente
3

VBA-Script para MS-Solución:

Se recomienda eliminar la actualización con errores, si es posible (si no prueba mi código), al menos para las versiones de MSI. Consulte la respuesta https://stackoverflow.com/a/58833831/9439330 .

Para las versiones CTR (Hacer clic y ejecutar), debe eliminar todas las actualizaciones de noviembre de Office, lo que puede causar serios problemas de seguridad (no estoy seguro de si se eliminarán las correcciones críticas).

De los comentarios de @ Eric:

  • Si utiliza Table.Tablenamepara vincular formularios, se desvinculan ya que el antiguo nombre de tabla ahora es un nombre de consulta.
  • OpenRecordSet(FormerTableNowAQuery, dbOpenTable) fallará (ya que ahora es una consulta, ya no es una tabla)

¡Precaución! Simplemente probado rápidamente en Northwind.accdb en Office 2013 x86 CTR ¡ Sin garantía!

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

Para las pruebas:

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
ComputerVersteher
fuente
44
Tenga en cuenta que esta solución alternativa arruinará los subformularios vinculados a las tablas (será necesario que se vuelvan a vincular a las consultas) y que el código funcione con tabledefs con un nombre de tabla codificado. Use con mucha precaución, lo más probable es que esto corrija un error solo para crear dos nuevos dependiendo de lo que esté haciendo su aplicación.
Erik A
@ErikA Por supuesto, solo una solución, pero puedo vincularme Inventory to reorder Subform for Homea la Inventorytabla en Homeforma, sin problemas. Incluso no se recomienda vincular formularios a consultas en lugar de tablas (¿no se vincula a una tabla como Select * From table?).
ComputerVersteher
2
Si enlazo un subformulario a una tabla, generalmente lo hago usando la Table.TableNamenotación. Si lo haces SELECT * FROM TableName, por supuesto que estás bien. Pero si lo usa Table.TableName, su subformulario se desatará si cambia el nombre de la tabla.
Erik A
@ErikA: Eso es cierto. ¿Algún beneficio al hacer eso?
ComputerVersteher
3
No que yo sepa, excepto que es más breve. Sin TableDefs!MyTableName.OpenRecordset(dbOpenTable)embargo, hay una ventaja sustancial de (soporte de búsqueda de índice), que también tiendo a usar y también causará errores con su enfoque
Erik A,
2

Reemplacé el currentDb.Executey Docmd.RunSQLcon una función auxiliar. Eso puede preprocesar y cambiar la instrucción SQL si cualquier instrucción de actualización contiene solo una tabla. Ya tengo una dualtabla ( una sola fila, una sola columna), así que elegí una opción de tabla falsa.

Nota : Esto no cambiará sus objetos de consulta. Solo ayudará a las ejecuciones de SQL a través de 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.

Esto es solo un concepto (If it's a single table update modify the sql before execution). Adaptarlo según sus necesidades. Este método no crea consultas de reemplazo para cada tabla (que puede ser la forma más fácil pero tiene sus propios inconvenientes, es decir, problemas de rendimiento)

+ Puntos: puede seguir utilizando este ayudante incluso después de que MS solucione el error, no cambiará nada. En caso de que el futuro traiga otro problema, está listo para pre-processsu SQL en un solo lugar. No elegí el método de desinstalación porque eso requiere acceso de administrador + va a tomar demasiado tiempo para que todos tengan la versión correcta + incluso si desinstalas, la política de grupo de algunos usuarios finales instala la última actualización nuevamente. Has vuelto al mismo problema.

Si tiene acceso al código fuente use this methody está 100% seguro de que ningún usuario final tiene el problema.

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

Ahora solo CTRL+F

Buscar y reemplazar docmd.RunSQLconhelper.Execute

Buscar y reemplazar [currentdb|dbengine|or your dbobject].executeconhelper.execute

¡que te diviertas!

Krish
fuente
0

Ok, también intervenir aquí, porque a pesar de que este error se ha solucionado, esa solución aún no se ha completado por completo a través de varias empresas en las que los usuarios finales no pueden actualizar (como mi empleador ...)

Aquí está mi solución para DoCmd.RunSQL "UPDATE users SET uname= 'bob' WHERE usercode=1". Simplemente comente la consulta ofensiva y coloque el código a continuación.

    '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

No puedo decir que sea bonito, pero hace el trabajo.

Chaosbydesign
fuente