如何使用ODP.NET在存储过程中从Oracle动态SQL返回记录

问题描述:

我试图弄清楚如何获取正在存储过程中保存的动态SQL查询的结果。如何使用ODP.NET在存储过程中从Oracle动态SQL返回记录

的存储过程很简单:

CREATE OR REPLACE PROCEDURE PORT_CALL_PROCEDEURE(queryin IN varchar2,result out varchar2) 
is 

BEGIN 

    dbms_output.put_line(queryin); 
    EXECUTE IMMEDIATE queryin;  
END ; 

的方式我'从VS调用它是:

OracleCommand oracmd = GetCommand("PORT_CALL_PROCEDEURE", oraconn); 
oraconn.Open(); 
string row = string.Empty; 
StringBuilder sb = new StringBuilder(); 
sb.Append("SELECT * into result Where port = 'MSO'and Map = 'Local'"); 
sb.Append(" FROM VESSEL"); 
string commandString = sb.ToString(); 
command.Parameters.Add("query_in", OracleDbType.Varchar2, 10000000,  commandString, ParameterDirection.Input); 
command.Parameters.Add("result", OracleDbType.Varchar2, 10000000,  `commandString, ParameterDirection.Output);` 
oracmd.ExecuteNonQuery(); 

我'得到一个例外:

{"ORA-00905: missing keyword 
    ORA-06512: at \"BOAZ.PORT_CALL_PROCEDEURE\", line 7 
    ORA-06512: at line 1"} 

任何帮帮我? 谢谢。

+0

调用存储过程仅用于执行标量查询的目的是什么?通常这个动作可以在不使用存储过程的情况下完成!如果您不知道,请查看OracleCommand.ExecuteScalar方法。 http://docs.oracle.com/cd/E11882_01/win.112/e23174/OracleCommandClass。htm#i998581 –

+0

查询只是一个例子,我将查询编辑到了正确的一个。 –

+0

这并不会改变我评论的意义!你看到我发布的文档链接了吗?还有一个简短的例子,显示应该如何完成这些事情。如果您不知道如何在PL/SQL中正确执行动态SQL,那么这不是绝对适合您的情况,这是另一个问题,但尝试将这两件事分开! –

该解决方案为我工作:

甲骨文C程序颂:

CREATE OR REPLACE PROCEDURE PORT_CALL_PROCEDEURE 
    (queryin IN varchar2, result out varchar2) is 
BEGIN 
    dbms_output.put_line(queryin); 
    EXECUTE IMMEDIATE queryin into result; 
END ; 

C#代码:

OracleCommand oracmd = new OracleCommand("PORT_CALL_PROCEDEURE", oraconn); 
oracmd.CommandType = CommandType.StoredProcedure; 
oracmd.Parameters.Add("query_in", OracleDbType.Varchar2, 10000000, 
    "select * from dual where dummy='X'", ParameterDirection.Input); 
oracmd.Parameters.Add("result", OracleDbType.Varchar2, 10000000, 
    null, ParameterDirection.Output); 
oracmd.ExecuteNonQuery(); 
Console.WriteLine(oracmd.Parameters["result"].Value); 

这将为标,VARCHAR值工作。要获得结果作为DataTable,您需要将Oracle过程中的类型更改为sys_refcursor,并将C#中的类型更改为RefCursor(未对其进行测试)。

错误说EXECUTE IMMEDIATE不明白result

修改execute immediate

execute immediate queryin into result. 

发送查询像

select clmn from tbl where .... 

演示:

declare 
v_name varchar2(50); 
begin 
execute immediate q'{select 'my name' into v_name from dual}'; 
dbms_output.put_line(v_name); 
end; 
/
ORA-00905: missing keyword 
ORA-06512: at line 4 
00905. 00000 - "missing keyword" 


declare 
v_name nvarchar2(50); 
begin 
execute immediate q'{select 'my name' from dual}' into v_name; 
dbms_output.put_line(v_name); 
end; 
/
anonymous block completed 
my name 

要执行该查询,您不需要动态SQL,也不需要PL/SQL存储过程。如果你想要学习这两件事情,没有什么不好的,但是试着只做一件你不知道的事情。这将帮助您识别错误。

在你的代码由三个主要错误:

  1. 在查询的WHERE子句从
  2. SELECT INTO之前的工作只能在PL/SQL块,并执行即时不出手
  3. DBMS_OUTPUT不会在.NET中工作,如果你不叫DBMS_OUTPUT.GET_LINES,如果你不这样做所有需要的东西越来越之前做的工作

因此,这是C#代码你会以简单和正确的方式执行它:

OracleConnection connection = new OracleConnection(); 
connection.ConnectionString = "xxxYYYzzz"; 
connection.Open(); 

OracleCommand oracmd = connection.CreateCommand(); 
oraCmd.CommandText = 
@"SELECT * 
FROM VESSEL 
Where port = 'MSO'and Map = 'Local'".Replace("\r", ""); // Oracle SQL Parset doesn't like '\r' char 
object res = oraCmd.ExecuteScalar(); 

Console.WriteLine(res);