2011-01-29 9 views
7

próbuję wykonać kwerendy SQL na bazie danych MS Access, zawierający funkcję „Replace”:wyjątek podczas próby wykonania „Zamień” przeciwko MS Access

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

Jeśli uruchomić tę kwerendę od wewnątrz MS Dostęp (aplikacja) działa dobrze. Ale kiedy próbuję uruchomić go z mojej aplikacji, wyjątek jest generowany.

Wyjątek:

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

Dlaczego otrzymuję ten wyjątek?

Więcej informacji:

  • Moja aplikacja jest aplikacją WPF
  • Używam .NET 3.5
  • uruchomić MS Access 2007
  • Moja ConnectionString jest „Provider = Microsoft.ACE .OLEDB.12.0; Data Source = C: \ MójFolder \ MyDatabase.accdb "

Mój kod dostępu do bazy danych wygląda mniej więcej tak, gdzie będę po prostu przekazać we wspomnianym SQL jako ciąg:

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

(Niektóre jak kod obsługi błędów usunięte dla zwięzłość. Zauważ, że buduję tylko szybki prototyp, więc ten kod instalacyjny nigdy nie będzie użyty na prawdę, więc proszę, proszę. ;) Nadal potrzebuję tego do pracy ...)

Alternatywne rozwiązanie?

Jeśli nie można uzyskać REPLACE do pracy, może znasz jakieś alternatywne rozwiązanie? Mogłem pobrać wszystkie wiersze, które chcę zaktualizować, zrobić ten ciąg w kodzie, a następnie zaktualizować wiersze w bazie danych. Ale może to być wiele zapytań SQL (jeden do pobrania i jeden do każdego wiersza do aktualizacji) i nie byłoby to bardzo eleganckie rozwiązanie ...

Odpowiedz

0

Nie jestem pewien, czy jest to związane z problemem, który masz, ale Wystąpił problem podczas uruchamiania aktualizacji, która zawierała funkcję zamiany w programie Access 2010, która po prostu wróciłaby bez błędu - nic. Byłem faktycznie uruchomiony z OleDb w .NET i wreszcie zorientowałem się, że muszę ustawić klucz rejestru, aby wyłączyć "Tryb piaskownicy".

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

nadzieję, że pomoże.

4

W trybie interaktywnym Access Expression Service zapewnia dostęp do funkcji zdefiniowanych przez użytkownika i VBA, ale usługa Access Expression nie jest dostępna z poziomu Access. Podczas uzyskiwania dostępu do danych Jet/ACE przez ODBC lub OLEDB dostępna jest tylko ograniczona liczba funkcji. Replace() nie jest jednym z nich. Jednakże możesz użyć InStr() i Len() do replikowania funkcji funkcji Replace(), ale byłoby to dość brzydkie.

+0

Jest to dobre rozwiązanie, ale nie rozwiązuje kwestię plakatów. –

+0

Nie mam rozwiązania (nigdy nie pracuję poza Access!), Ale miałem nadzieję, że wskazanie tego może prowadzić do odpowiedzi od kogoś, kto może pomóc, być może ktoś, kto chce zhakować brzydkie wyrażenie wymagane za pomocą InStr() i Len(), aby wykonać zadanie. –

+1

"Być może ktoś chce zhakować razem brzydki ekspres" - gotowe! ;) – onedaywhen

4

jest to niemożliwe, aby uzyskać REPLACE do pracę, może znasz jakiś alternatywnego rozwiązania?

Oto "dość brzydki" alternatywne podejście wspomniał przez @ 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

Pytanie o to, jak inteligentnie optymalizator zapytań Jet/ACE wchodzi w interakcję z usługą ekspresji Jet. To znaczy, czy będzie oceniać 'INSTR (MyColumn, 'MyOldSubstring')' i 'LEN ('MyOldSubstring')' za każdym razem, gdy go napotka, czy będzie oceniać raz i buforował wynik? Wiem, że optymalizator zapytań Jet/ACE jest inteligentny z "pionową" optymalizacją, tj. Oceniając tylko raz każde wyrażenie, które jest takie samo dla wszystkich wierszy, ale martwię się, że nie jest tak mądry z "poziomą" optymalizacją, tj. to samo wyrażenie tylko raz w rzędzie. [kontynuacja ...] –

+0

Spodziewałbym się, że gdybyś miał dwie wyliczone kolumny: Len (MyField) AS Length1' i 'Len (MyField) + 3 As Length2', że byłby oceniany tylko raz. Ale kiedy wyrażenia są argumentami przekazywanymi do innej funkcji, obawiam się, że nie będą one efektywnie oceniane. Niestety, interakcja z usługami ekspresowymi Jet/Access nie jest udokumentowana w SHOWPLAN, więc nie można tego w żaden sposób poznać. Można ocenić, w jaki sposób optymalizowane są wywołania usługi wyrażania dostępu, pisząc funkcje UDF, które są wyprowadzane za pomocą polecenia Debug.Print za każdym razem, gdy są wywoływane, ale można to zrobić za pomocą funkcji innych niż UDF. –

+0

Dobra robota, BTW. Oczywiście, jest to po prostu implementacja SQL UDF, które musieliśmy napisać, zanim Access uzyska Funkcję Replace() (A2000), ale wciąż jest brudny (z powodu wszystkich powtórzeń). –

Powiązane problemy