Oracle SQL 查询仅在一个进程中失败:“ORA-01405:获取的列值为 NULL”
我试图在我构建的“插件”中调用系统存储过程。当我在测试应用程序中测试我的插件时,它工作正常。当我在正在构建的目标应用程序中运行该插件时,我从 Oracle 得到了一个没有任何意义的异常。
我使用的是 Oracle 服务器 11.2.0.1.0 和 ODP.NET 2.112.2.0。
这是我的测试应用程序中来自 ODP.NET 的调试跟踪:
(ENTRY) OracleConnection::OracleConnection(1)
(POOL) New connection pool created for: "Data Source=orcl;User ID=scott;"
(ENTRY) OracleConnection::CreateCommand()
OpsSqlPrepare2():SQL: begin DBMS_AQADM.START_QUEUE(queue_name => 'MyQueue'); end;
(EXIT) OpsSqlExecuteNonQuery(): RetCode=0 Line=877
(EXIT) OracleCommand::ExecuteNonQuery()
(ENTRY) OracleConnection::Dispose()
(ENTRY) OracleConnection::Close()
这是来自目标应用程序中运行的相同代码的 ODP.NET 调试跟踪:
(ENTRY) OracleConnection::OracleConnection(1)
(POOL) New connection pool created for: "Data Source=orcl;User ID=scott;"
(ENTRY) OracleConnection::CreateCommand()
OpsSqlPrepare2():SQL: begin DBMS_AQADM.START_QUEUE(queue_name => 'MyQueue'); end;
(EXIT) OpsSqlExecuteNonQuery(): RetCode=0 Line=877
(EXIT) OracleCommand::ExecuteNonQuery()
(ENTRY) OpsErrGetOpoCtx()
(ERROR) Oracle error code=1405; ORA-01405: fetched column value is NULL
(EXIT) OpsErrGetOpoCtx(): RetCode=0 Line=137
(ENTRY) OracleConnection::Dispose()
(ENTRY) OracleConnection::Close()
我不知道测试/目标应用程序之间可能有什么不同。这两个进程都作为本地管理员组的成员运行。两者都使用相同的连接字符串。两者都运行相同的 .NET 代码,但数据库服务器的结果不同。这里可能发生了什么?
I'm trying to call a system stored procedure in a "plugin" that I've built. When I test my plugin out in a test application, it works fine. When I run the plugin in the targeted app I'm building it for, I get an exception from Oracle that doesn't make any sense.
I'm using Oracle server 11.2.0.1.0, and ODP.NET 2.112.2.0.
Here's the debug trace from ODP.NET from my test app:
(ENTRY) OracleConnection::OracleConnection(1)
(POOL) New connection pool created for: "Data Source=orcl;User ID=scott;"
(ENTRY) OracleConnection::CreateCommand()
OpsSqlPrepare2():SQL: begin DBMS_AQADM.START_QUEUE(queue_name => 'MyQueue'); end;
(EXIT) OpsSqlExecuteNonQuery(): RetCode=0 Line=877
(EXIT) OracleCommand::ExecuteNonQuery()
(ENTRY) OracleConnection::Dispose()
(ENTRY) OracleConnection::Close()
And here's debug trace from ODP.NET from the same code running in the targeted app:
(ENTRY) OracleConnection::OracleConnection(1)
(POOL) New connection pool created for: "Data Source=orcl;User ID=scott;"
(ENTRY) OracleConnection::CreateCommand()
OpsSqlPrepare2():SQL: begin DBMS_AQADM.START_QUEUE(queue_name => 'MyQueue'); end;
(EXIT) OpsSqlExecuteNonQuery(): RetCode=0 Line=877
(EXIT) OracleCommand::ExecuteNonQuery()
(ENTRY) OpsErrGetOpoCtx()
(ERROR) Oracle error code=1405; ORA-01405: fetched column value is NULL
(EXIT) OpsErrGetOpoCtx(): RetCode=0 Line=137
(ENTRY) OracleConnection::Dispose()
(ENTRY) OracleConnection::Close()
I'm at a loss as to what could be different between the test/target applications. Both processes are running as members of the local Administrators group. Both are using the same connection string. Both are running the same .NET code, but with a different outcome from the database server. What could be going on here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
此错误来自旧的 OCI & prec 编译的代码,其中需要设置指示符变量来指示字段返回 null。当没有声明指示变量时,如果遇到空值,则会触发此错误。显然,一些较旧的代码仍然位于您所做的调用之下。
换句话说,这是一个数据问题。我不知道从哪里开始随意寻找。
This error comes from old OCI & prec-compiled code where an indicator variable was required to be set to indicate a null return for the field. When there is no indicator variable declared, this error is triggered if a null value is encountered. Obviously, some older code is still layered under the calls you made.
In other words, it is a data issue. I don't know where to start looking offhand.
事实证明,我的目标应用程序正在分布式 XA 事务(在我的例子中为 MSDTC)中执行我的插件代码。对
DBMS_AQADM.START_QUEUE
的调用有一个我不知道的隐式COMMIT;
。在这种情况下,错误消息显然没有任何帮助。解决方案是将我的调用包装在以下内容中:
这会导致对 DBMS_AQADM.START_QUEUE 的调用在环境事务之外运行。
It turns out that my target application was executing my plugin code while in Distributed XA Transaction (MSDTC in my case). The call to
DBMS_AQADM.START_QUEUE
has an implicitCOMMIT;
that I wasn't aware of. The error message is obviously not helpful at all in this case.The solution is to wrap my call in in the following:
This causes the call to
DBMS_AQADM.START_QUEUE
to run outside of the ambient transaction.