2011-01-29 19 views
7

Estoy tratando de ejecutar una consulta SQL en una base de datos de MS Access que contiene una función "reemplazar":Excepción al intentar ejecutar "reemplazar" en contra de MS Access

UPDATE MyTable 
    SET MyColumn = REPLACE(MyColumn, 'MyOldSubstring', 'MyNewSubstring') 
WHERE Id = 10; 

Si me quedo esta consulta desde el interior de la EM Access (la aplicación) funciona bien. Pero cuando intento ejecutarlo desde mi aplicación, se lanza una excepción.

La excepción:

System.Data.OleDb.OleDbException was unhandled 
    Message="Undefined function 'REPLACE' in expression." 
    Source="Microsoft Office Access Database Engine" 
    ErrorCode=-2147217900 
    StackTrace: 
     at System.Data.OleDb.OleDbCommand.ExecuteCommandTextErrorHandling(OleDbHResult hr) 
     at System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBPARAMS dbParams, Object& executeResult) 
     at System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object& executeResult) 
     at System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior behavior, Object& executeResult) 
     at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method) 
     at System.Data.OleDb.OleDbCommand.ExecuteNonQuery() 
     ... 

¿Por qué recibo esta excepción?

Más información:

  • Mi aplicación es una aplicación de WPF
  • estoy usando .NET 3.5
  • corro MS Access 2007
  • Mi connectionstring es "Provider = Microsoft.ACE .OLEDB.12.0; Origen de datos = C: \ MyFolder \ MyDatabase.accdb "

Mi código de acceso a la base de datos se ve más o menos así, donde voy a pasar en el SQL mencionado como una cadena:

public void ExecuteNonQuery(string sql) 
{ 
    OleDbCommand command = new OleDbCommand(sql); 
    OleDbConnection connection = new OleDbConnection(ConnectionString); 
    command.Connection = connection; 

    try 
    { 
     connection.Open(); 
     command.ExecuteNonQuery(); 
    } 
    catch 
    { 
     throw; 
    } 
    finally 
    { 
     connection.Close(); 
    } 
} 

(Algunos código como el manejo de errores removido por razones de brevedad. Observe que solo estoy construyendo un prototipo rápido para que este código de plomería nunca se use de verdad, así que tenga paciencia. ;) Todavía necesito que esto funcione ...)

¿Solución alternativa?

Si no puede hacer que el REEMPLAZO funcione, ¿tal vez conozca alguna solución alternativa? Podría buscar todas las filas que quiero actualizar, hacer esta cadena reemplazar en el código y luego actualizar las filas en la base de datos. Pero eso podría ser una gran cantidad de consultas SQL (una para buscar y otra para cada fila para actualizar) y no sería una solución muy elegante ...

Respuesta

0

No estoy seguro de si esto está relacionado con el problema que tiene pero Estaba teniendo un problema al ejecutar una actualización que contenía una función de reemplazo en Access 2010 que simplemente volvería sin error, nada. Lo estaba ejecutando desde OleDb en .NET y finalmente descubrí que necesitaba establecer una clave de registro para desactivar el "Modo de espacio aislado".

http://office.microsoft.com/en-us/access-help/use-sandbox-mode-in-access-2007-HA010167429.aspx

Espero que ayude.

4

En Acceso interactivo, el Servicio de Expresión de Acceso se ocupa de proporcionarle acceso a las funciones de VBA y definidas por el usuario, pero el Servicio de Expresión de Acceso no está disponible desde fuera de Access. Al acceder a los datos de Jet/ACE a través de ODBC u OLEDB, solo está disponible un número limitado de funciones. Reemplazar() no es uno de ellos. Sin embargo, es posible que pueda utilizar InStr() y Len() para replicar la funcionalidad de la función Reemplazar(), pero sería bastante feo.

+0

Es una buena respuesta, pero no resuelve la cuestión carteles. –

+0

No tengo una solución (¡nunca trabajo fuera de Access!), Pero esperaba que señalar esto podría llevar a una respuesta de alguien que podría ayudar, tal vez alguien dispuesto a hackear juntos la fea expresión requerida usando InStr() y Len() para hacer el trabajo. –

+1

"tal vez alguien dispuesto a hackear juntos la fea expresión requerida" - hecho! ;) – onedaywhen

4

es imposible obtener la REPLACE a trabajo, tal vez usted sabe de alguna solución alternativa ?

Aquí está el enfoque alternativo "bastante fea" aludido por @ David-W-Fenton:

UPDATE MyTable 
    SET MyColumn = MID(
         MyColumn, 
         1, 
         INSTR(MyColumn, 'MyOldSubstring') 
         - 1 
        ) 
        + 'MyNewSubstring' 
        + MID(
          MyColumn, 
          INSTR(MyColumn, 'MyOldSubstring') 
           + LEN('MyOldSubstring'), 
          LEN(MyColumn) 
           - INSTR(MyColumn, 'MyOldSubstring') 
           - LEN('MyOldSubstring') 
           + 1 
         ) 
WHERE INSTR(MyColumn, 'MyOldSubstring') > 0 
     AND Id = 10; 
+1

La pregunta sobre esto es qué tan inteligentemente el optimizador de consultas Jet/ACE interactúa con el servicio de expresión Jet. Es decir, ¿evaluará 'INSTR (MyColumn, 'MyOldSubstring')' y 'LEN ('MyOldSubstring')' cada vez que lo encuentre, o lo evaluará una vez y almacenará en caché el resultado? Sé que el optimizador de consultas Jet/ACE es inteligente con optimización "vertical", es decir, evaluando solo una vez cualquier expresión que sea igual para todas las filas, pero me preocupa que no sea tan inteligente con la optimización "horizontal", es decir, evaluar el misma expresión solo una vez por fila. [continúa ...] –

+0

Esperaría que si tuviera dos columnas calculadas 'Len (MyField) AS Length1' y' Len (MyField) + 3 As Length2' que se evaluarían una sola vez. Pero cuando las expresiones son argumentos pasados ​​a otra función, me preocupa que no se evalúen de manera eficiente. Desafortunadamente, la interacción con los servicios de expresión de Jet/Access no está documentada en SHOWPLAN, por lo que no hay una manera real de saberlo. Podría evaluar cómo se optimizan las llamadas al servicio de expresión de Access escribiendo UDF que salen con Debug.Print cada vez que son llamadas, pero puede hacerlo con no-UDF. –

+0

Buen trabajo, por cierto. Por supuesto, es solo una implementación de SQL de las UDF que tuvimos que escribir antes de que Access obtuviera un funcitón Replace() (A2000), pero sigue estando desordenado (debido a toda la repetición). –

Cuestiones relacionadas