2011-01-29 36 views
7

Tôi đang cố gắng để thực hiện một truy vấn SQL chống lại một cơ sở dữ liệu MS Access chứa một "REPLACE" chức năng:ngoại lệ khi cố gắng thực hiện "REPLACE" chống lại MS Access

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

Nếu tôi chạy truy vấn này từ bên trong MS Truy cập (ứng dụng) nó hoạt động tốt. Nhưng khi tôi cố gắng chạy nó từ ứng dụng của tôi, một ngoại lệ được ném ra.

Trường hợp ngoại lệ:

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

Tại sao tôi nhận ngoại lệ này? Thông tin

thêm:

  • Ứng dụng của tôi là một ứng dụng WPF
  • Tôi đang sử dụng .NET 3.5
  • tôi chạy MS Access 2007
  • connectionstring của tôi là "Provider = Microsoft.ACE .OLEDB.12.0; Nguồn dữ liệu = C: \ MyFolder \ MyDatabase.accdb "

Mã truy cập cơ sở dữ liệu của tôi trông giống như thế này, nơi tôi sẽ chỉ cần vượt qua trong SQL đề cập như là một chuỗi:

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

(Một số mã như lỗi xử lý loại bỏ cho ngắn gọn. Quan sát rằng tôi chỉ xây dựng một nguyên mẫu nhanh chóng vì vậy mã hệ thống ống nước này sẽ không bao giờ được sử dụng cho thực tế, vì vậy hãy chịu đựng với nó. ;) Tôi vẫn cần điều này để làm việc mặc dù ...)

Giải pháp thay thế?

Nếu không thể lấy REPLACE hoạt động, có thể bạn biết một số giải pháp thay thế? Tôi có thể lấy tất cả các hàng tôi muốn cập nhật, làm chuỗi này thay thế trong mã và sau đó cập nhật các hàng trong cơ sở dữ liệu. Nhưng đó có thể là rất nhiều truy vấn SQL (một để tìm nạp và một cho mỗi hàng để cập nhật) và sẽ không phải là một giải pháp rất thanh lịch ...

Trả lời

0

Không chắc chắn nếu điều này liên quan đến vấn đề bạn đang gặp phải Tôi đã gặp sự cố khi chạy bản cập nhật chứa chức năng thay thế trong Access 2010 mà sẽ chỉ trả về mà không có lỗi - không có gì. Tôi đã thực sự chạy nó từ OleDb trong. NET và cuối cùng đã tìm ra tôi cần thiết để thiết lập một khóa registry để tắt "Sandboxed Mode".

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

Hy vọng điều đó sẽ hữu ích.

4

Trong truy cập tương tác, dịch vụ biểu thức truy cập sẽ đảm bảo cung cấp cho bạn quyền truy cập vào các hàm do người dùng xác định và VBA, nhưng dịch vụ biểu thức truy cập không khả dụng từ bên ngoài Access. Khi truy cập dữ liệu Jet/ACE qua ODBC hoặc OLEDB, chỉ có một số chức năng giới hạn có sẵn. Replace() không phải là một trong số chúng. Tuy nhiên, bạn có thể sử dụng InStr() và Len() để nhân rộng chức năng của hàm Replace(), nhưng nó sẽ khá xấu xí.

+0

Đó là câu trả lời hay nhưng không giải quyết được câu hỏi áp phích. –

+0

Tôi không có giải pháp (tôi không bao giờ làm việc bên ngoài Access!), Nhưng tôi hy vọng rằng việc chỉ ra điều này có thể dẫn đến câu trả lời từ người có thể giúp đỡ, có lẽ ai đó sẵn sàng tấn công với biểu hiện xấu xí sử dụng InStr() và Len() để thực hiện công việc. –

+1

"có lẽ ai đó sẵn sàng cùng nhau tấn công biểu hiện xấu xí" - xong! ;) – onedaywhen

4

nó là không thể để có được những REPLACE để công việc, có thể bạn biết một số giải pháp thay thế?

Đây là "khá xấu xí" cách tiếp cận khác ám chỉ bởi @ 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

Câu hỏi về việc này là cách trình tối ưu hóa truy vấn Jet/ACE thông minh tương tác với dịch vụ biểu thức Jet. Nghĩa là, nó sẽ đánh giá 'INSTR (MyColumn, 'MyOldSubstring')' và 'LEN ('MyOldSubstring')' mỗi khi nó gặp nó, hay nó sẽ đánh giá một lần và lưu lại kết quả? Tôi biết rằng trình tối ưu hóa truy vấn Jet/ACE thông minh với tối ưu hóa "dọc", nghĩa là chỉ đánh giá một lần bất kỳ biểu thức nào giống nhau cho tất cả các hàng, nhưng tôi lo rằng nó không thông minh với tối ưu hóa "ngang", tức là đánh giá chỉ biểu hiện một lần trên mỗi hàng. [tiếp tục ...] –

+0

Tôi hy vọng rằng nếu bạn có hai cột được tính toán 'Len (MyField) AS Length1' và' Len (MyField) + 3 As Length2' sẽ chỉ được đánh giá một lần. Nhưng khi các biểu thức là các đối số được truyền cho một hàm khác, tôi lo lắng rằng chúng sẽ không được đánh giá hiệu quả. Thật không may, sự tương tác với các dịch vụ biểu thức Jet/Access không được ghi lại trong SHOWPLAN, vì vậy không có cách nào thực sự để biết. Bạn có thể đánh giá cách các cuộc gọi đến dịch vụ biểu thức Access được tối ưu hóa bằng cách viết các UDF mà đầu ra với Debug.Print mỗi khi chúng được gọi, nhưng bạn có thể làm điều đó với các UDF không. –

+0

Công việc hay, BTW. Tất nhiên, nó chỉ là một thực hiện SQL của UDF mà chúng ta phải viết trước khi Access có một Replace() funciton (A2000), nhưng nó vẫn lộn xộn (vì tất cả sự lặp lại). –

Các vấn đề liên quan