我正在为Oracle DB编写一个定制的简单Web界面,使用ASP.NET,C#中的Web API项目和Oracle.DataAccess(ODP.NET)。这是一个教育项目,我正在设计一个大学课程的额外项目。我设计这个项目有几个原因,但结果是使用Oracle提供的工具(SQL Developer,Enterprise Manage Express等)不适合手头的任务。
我有一个API调用,可以接受查询字符串,对DBMS执行它,并将DBMS的输出作为JSON数据返回,以及一些额外的返回数据。这对于简单的SELECT查询和其他基本DDL / DML查询已经足够了。但是,现在我们正在分支到PL / SQL。
例如,我们执行的最基本的PL / SQL HELLO WORLD程序如下:
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello World');
END;
当我将此查询提供给我的C#API时,它确实成功执行。但是,我希望能够检索DBMS_OUTPUT.PUT_LINE调用的输出。
之前已经解决了这个问题,我已经研究了一些解决方案,并介绍了一个涉及在数据库上调用以下PL / SQL的代码:
BEGIN
Dbms_output.get_line(:line, :status);
END;
C#代码显然会在发送之前为请求创建并添加正确的参数对象。我打算重复调用此函数,直到NULL值返回,表示输出结束。然后将此数据添加到API返回的JSON对象中,以便Web界面可以显示输出。但是,此函数永远不会返回任何输出行。
我的预感(我自己还在学习Oracle,所以不确定)是服务器实际上没有输出数据,还是在PL / SQL匿名过程(Hello World)程序之后刷新了缓冲区饰面。
还建议将set serveroutput on;
添加到PL / SQL查询中,但这不起作用:它产生错误ORA-00922: missing or invalid option
。
以下是用于从DBMS_OUTPUT缓冲区检索输出行的实际C#代码:
private string GetDbmsOutputLine(OracleConnection conn)
{
OracleCommand command = new OracleCommand
{
CommandText = "begin dbms_output.get_line(:line, :status); end;",
CommandType = CommandType.Text,
Connection = conn,
};
OracleParameter lineParameter = new OracleParameter("line",
OracleDbType.Varchar2);
lineParameter.Size = 32000;
lineParameter.Direction = ParameterDirection.Output;
command.Parameters.Add(lineParameter);
OracleParameter statusParameter = new OracleParameter("status",
OracleDbType.Int32);
statusParameter.Direction = ParameterDirection.Output;
command.Parameters.Add(statusParameter);
command.ExecuteNonQuery();
if (command.Parameters["line"].Value is DBNull)
return null;
string line = command.Parameters["line"].Value as string;
return line;
}
编辑:我尝试在执行用户代码之前手动调用以下过程:BEGIN DBMS_OUTPUT.ENABLE(32768); END;
。这样执行时没有错误,但在执行此操作后,稍后对DBMS_OUTPUT.GET_LINE
的调用仍然返回null。
看起来可能发生的事情是,每次我对数据库执行新查询时,即使它位于同一连接上,也要清除DBMS_OUTPUT缓冲区。我不确定是否是这种情况,但它似乎是 - 没有其他任何东西可以解释缓冲区中缺少数据。
仍在寻找处理此问题的方法......
要记住的要点:
OracleCommand
对象中来维护它。从理论上讲,这应该意味着保持缓冲区,但似乎并非如此。我写的数据首先没有进入缓冲区,或者每当实际对数据库连接执行OracleCommand
对象时刷新缓冲区。答案 0 :(得分:0)
有一点需要注意,实际上你永远不会编写代码,希望任何人都能看到你试图写入SELECT * FROM data_blocks WHERE MATCH(tags) AGAINST("+[16]");
的数据...
在会话中,您需要调用来分配dbms_output
写入的缓冲区。根据Oracle版本,您可以传入dbms_output
以指示您需要无限制的缓冲区大小。在旧版本中,您需要分配固定的缓冲区大小(如果您尝试向缓冲区写入太多数据,则会收到错误)。然后,您将调用调用null
的过程。最后,您可以致电dbms_output.put[_line]
。请注意,所有这三件事都必须在单个会话的上下文中发生。每个会话都有一个单独的dbms_output.get[_line]
缓冲区(或没有dbms_output
缓冲区)。