2011-01-29 20 views
7

Sto cercando di eseguire una query SQL su un database MS Access che contiene una funzione di "REPLACE":Eccezione quando si cerca di eseguire "SOSTITUIRE" contro MS Access

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

Se eseguo questa query dall'interno MS Accedi (l'applicazione) funziona bene. Ma quando provo ad eseguirlo dalla mia applicazione viene lanciata un'eccezione.

L'eccezione:

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() 
     ... 

Perché ottengo questa eccezione?

Maggiori informazioni:

  • La mia applicazione è un'applicazione WPF
  • sto usando .NET 3.5
  • corro MS Access 2007
  • mio connectionstring è "Provider = Microsoft.ACE .OLEDB.12.0; Origine dati = C: \ MyFolder \ MyDatabase.accdb "

Il mio codice di accesso al database è simile a questo, dove mi limiterò a passare in SQL citato come una stringa:

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(); 
    } 
} 

(Alcuni codice come la gestione degli errori rimossa per brevità. Osserva che sto solo costruendo un prototipo rapido, quindi questo codice idraulico non verrà mai utilizzato per davvero, quindi ti prego di sopportarlo. ;) Ho ancora bisogno di questo per lavorare però ...)

Soluzione alternativa?

Se è impossibile far funzionare la SOSTITUZIONE, forse sai qualche soluzione alternativa? Potrei recuperare tutte le righe che voglio aggiornare, fare questa stringa sostituire nel codice e quindi aggiornare le righe nel database. Ma potrebbe trattarsi di molte query SQL (una da recuperare e una per ogni riga da aggiornare) e non sarebbe una soluzione molto elegante ...

risposta

0

Non sono sicuro se questo è correlato al problema che si sta avendo ma Stavo riscontrando un problema durante l'esecuzione di un aggiornamento che conteneva una funzione di sostituzione in Access 2010 che sarebbe appena tornata senza errori - nulla. In realtà lo stavo eseguendo da OleDb in .NET e alla fine ho capito che avevo bisogno di impostare una chiave di registro per disattivare la "Modalità sandbox".

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

Speranza che aiuta.

4

In Accesso interattivo, il servizio di accesso alle espressioni si occupa di fornire l'accesso alle funzioni VBA definite dall'utente, ma il servizio Espressione accesso non è disponibile dall'accesso esterno. Quando si accede a dati Jet/ACE tramite ODBC o OLEDB, è disponibile solo un numero limitato di funzioni. Sostituisci() non è uno di questi. Tuttavia, potresti essere in grado di utilizzare InStr() e Len() per replicare la funzionalità della funzione Replace(), ma sarebbe abbastanza brutto.

+0

E 'una buona risposta, ma non risolve la questione manifesti. –

+0

Non ho una soluzione (non lavoro mai al di fuori di Access!), Ma speravo che il fatto di indicarlo potesse portare a una risposta da parte di qualcuno che potrebbe aiutare, forse qualcuno disposto a mettere insieme la brutta espressione richiesta usando InStr() e Len() per fare il lavoro. –

+1

"forse qualcuno disposto a hackerare insieme la brutta espressione richiesta" - fatto! ;) – onedaywhen

4

è impossibile ottenere il REPLACE a lavoro, forse si sa di alcuni soluzione alternativa?

Ecco l'approccio alternativo "abbastanza brutto" allude @ 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 domanda su questo è il modo intelligente in cui l'ottimizzatore di query Jet/ACE interagisce con il servizio di espressioni Jet. Vale a dire, valuterà 'INSTR (MyColumn, 'MyOldSubstring')' e 'LEN ('MyOldSubstring')' ogni volta che lo incontra, o valuterà una volta e memorizzerà il risultato? So che l'ottimizzatore di query Jet/ACE è intelligente con l'ottimizzazione "verticale", vale a dire, valuta solo una volta qualsiasi espressione uguale per tutte le righe, ma temo che non sia così intelligente con l'ottimizzazione "orizzontale", cioè, valutando il stessa espressione solo una volta per riga. [continua ...] –

+0

Mi sarei aspettato che se avessi due colonne calcolate 'Len (MyField) AS Length1' e' Len (MyField) + 3 As Length2' che sarebbero state valutate solo una volta. Ma quando le espressioni sono argomenti passati a un'altra funzione, temo che non verranno valutate in modo efficiente. Sfortunatamente, l'interazione con i servizi di espressione Jet/Access non è documentata in SHOWPLAN, quindi non c'è un modo reale per sapere. È possibile valutare in che modo le chiamate al servizio di espressione Access vengono ottimizzate scrivendo UDF che vengono emesse con Debug.Print ogni volta che vengono chiamate, ma è possibile farlo con le non-UDF. –

+0

Bel lavoro, a proposito. Naturalmente, è solo un'implementazione SQL delle UDF che dovevamo scrivere prima che Access avesse una funzione Replace() (A2000), ma è ancora disordinato (a causa di tutte le ripetizioni). –

Problemi correlati