首页 > 解决方案 > 插入ORACLE TABLE Delphi Belin 10.1 upd 2时FireDAC“表或视图不存在”

问题描述

我们正在将我们的代码库从带有 FireDAC 8.0.5 的 Delphi XE3 迁移到带有 FireDAC 15.0.1(Build 86746)的 Delphi Berlin 10.1 Upd 2。使用 MS Sql Server 一切顺利,但使用 ORACLE 却是另一段历史。

在整个应用程序源代码中,我们使用了大量带有 sql 指令的 TAdQuery,例如

AdQuery1.Sql.Text := 'SELECT FIELD1, FIELD2 FROM TABLE1';

为了插入一条记录,我们使用 Append 或 Insert 方法,像这样

AdQuery1.Insert; //或者 AdQuery1.Append;

在调用它的 Post 方法之后,组件内部会创建一个 INSERT sql 语句,如下所示

INSERT INTO TABLE1 (FIELD1, FIELD2) VALUES(:FIELD1, :FIELD2)

所以记录被成功插入。

现在,在 Delphi Berlin 中使用 TFdQuery,组件在内部创建一个 INSERT sql 语句,像这样

INSERT INTO USERNAME.TABLE1 (FIELD1, FIELD2) VALUES(:FIELD1, :FIELD2)

[FireDAC][Phys][Ora]失败ORA-00942: 表或视图不存在

发生这种情况是因为在我们的 Oracle 数据库中,TABLE1 是在名为 MAIN_SCHEMA 的模式中创建的,我们使用公共同义词访问它。

为了找到解决方法,我们比较了 FireDAC 源代码,发现

在 Delphi XE3 中,单元uADDAptManager.pas在其函数TADDAptTableAdapter.GetUpdateRowCommand上调用oConn.CreateCommandGenerator(oCmdGen, nil);

在 Delphi Berlin 中,FireDAC.DApt.pas 单元对其函数TFDDAptTableAdapter.GetUpdateRowCommand 调用oConn.CreateCommandGenerator(oCmdGen, GetSelectCommand);

只要第二个参数(称为 ACommand: IFDPhysCommand)不是 nil,就会返回连接用户名的表名(在名为TFDPhysCommandGenerator.GetFrom的函数中)。

如果我们添加'MetaCurSchema=MAIN_SCHEMA'到 TFdConnection 参数,它适用于不使用池连接的应用程序,但是我们有几个进程使用具有相同参数的池连接,甚至是 MetaCurSchema 参数,但它不起作用

我们能做些什么?

感谢您的帮助

标签: oracledelphisql-insertdatabase-schemafiredac

解决方案


我的理解是,最好使连接避免使用任何模式名称,而不是指定它。另外,请记住您已经使用公共同义词。

因此,根据文档:

完整的对象名称

FireDAC 支持完整的对象名称,包括目录和/或模式名称。

当为 StoredProcName、TableName 等指定短对象名称时,它们将使用当前目录和/或模式名称扩展为完整的对象名称。要覆盖或避免使用当前目录和/或模式名称,请使用MetaCurCatalogMetaCurSchema连接定义参数。例如:

[Oracle_Demo]
 DriverID=Ora  
 ...
 MetaCurCatalog=*
 MetaCurSchema=*

~ 来源:对象名称 (FireDAC) - docWiki

MetaCurSchema

指定应用程序的当前架构。如果未指定,则将从 DBMS 接收其值。当应用程序请求元数据但未指定模式名称时,FireDAC 将隐式使用当前模式。
如果MetaCurSchema是“*”,那么元数据参数中将省略模式名称。

~ 来源:通用连接参数 (FireDAC) - docWiki

那个星号(*)应该可以解决问题,如果是这样,请告诉我们。


推荐阅读