【问题标题】:Exception when trying to execute "REPLACE" against MS Access尝试对 MS Access 执行“REPLACE”时出现异常
【发布时间】:2011-06-17 14:22:21
【问题描述】:

我正在尝试对包含“REPLACE”函数的 MS Access 数据库执行 SQL 查询:

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

如果我从 MS Access(应用程序)内部运行此查询,它可以正常工作。但是当我尝试从我的应用程序运行它时,会引发异常。

例外:

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

为什么会出现此异常?

更多信息:

  • 我的应用程序是 WPF 应用程序
  • 我正在使用 .NET 3.5
  • 我运行 MS Access 2007
  • 我的连接字符串是“Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\MyFolder\MyDatabase.accdb”

我的数据库访问代码看起来像这样,我将在其中将提到的 SQL 作为字符串传递:

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

(为简洁起见,删除了一些像错误处理这样的代码。请注意,我只是在构建一个快速原型,所以这个管道代码永远不会被真正使用,所以请耐心等待。;)我仍然需要这可以工作......)

替代解决方案?

如果无法让 REPLACE 工作,也许您知道一些替代解决方案?我可以获取我想要更新的所有行,在代码中替换这个字符串,然后更新数据库中的行。但这可能是很多 SQL 查询(一个要获取,一个要更新的每一行)并且不是一个非常优雅的解决方案...

【问题讨论】:

    标签: .net ms-access replace


    【解决方案1】:

    【讨论】:

      【解决方案2】:

      不可能得到REPLACE 工作,也许你知道一些 替代解决方案?

      这是@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;
      

      【讨论】:

      • 关于这个的问题是 Jet/ACE 查询优化器在与 Jet 表达式服务交互时的智能程度。也就是说,它会在每次遇到它时评估INSTR(MyColumn, 'MyOldSubstring')LEN('MyOldSubstring'),还是会评估一次并缓存结果?我知道 Jet/ACE 查询优化器在“垂直”优化方面很聪明,即只对所有行都相同的任何表达式评估一次,但我担心它在“水平”优化方面并不那么聪明,即评估每行只有一次相同的表达式。 [继续...]
      • 我希望,如果您有两个计算列 Len(MyField) AS Length1Len(MyField) + 3 As Length2,它只会被评估一次。但是当表达式是传递给另一个函数的参数时,我担心它们不会被有效地评估。不幸的是,与 Jet/Access 表达式服务的交互没有记录在 SHOWPLAN 中,因此没有真正的方法可以知道。您可以通过编写每次调用时使用 Debug.Print 输出的 UDF 来评估对 Access 表达式服务的调用如何优化,但您可以使用非 UDF。
      • 干得好,顺便说一句。当然,这只是我们在 Access 获得 Replace() 函数 (A2000) 之前必须编写的 UDF 的 SQL 实现,但它仍然很乱(因为所有重复)。
      • 这必须在访问程序上?
      • @safi:你的问题不清楚。您是什么意思“关于访问程序”?应该是可以通过 ADO/OLEDB 或 ODBC 从外部 Access 执行的 SQL,因为它使用的所有函数都可用于 Jet/ACE 表达式服务。
      【解决方案3】:

      在交互式 Access 中,Access Expression Service 负责为您提供对用户定义和 VBA 函数的访问权限,但 Access Expression Service 在 Access 外部不可用。通过 ODBC 或 OLEDB 访问 Jet/ACE 数据时,只有有限数量的函数可用。 Replace() 不是其中之一。但是,您可以使用 InStr() 和 Len() 来复制 Replace() 函数的功能,但这会相当难看。

      【讨论】:

      • 我没有解决方案(我从不在 Access 之外工作!),但我希望指出这一点可能会得到可以提供帮助的人的回答,也许有人愿意将使用 InStr() 和 Len() 完成工作所需的丑陋表达式拼凑在一起。
      • “也许有人愿意将所需的丑陋表达拼凑在一起”——完成! ;)
      【解决方案4】:

      不确定这是否与您遇到的问题有关,但我在运行包含 Access 2010 中的替换功能的更新时遇到问题,该功能只会返回没有错误 - 没有。我实际上是从 .NET 中的 OleDb 运行它,最后发现我需要设置一个注册表项来关闭“沙盒模式”。

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

      希望对您有所帮助。

      【讨论】:

        猜你喜欢
        • 2019-01-15
        • 2012-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多