如何使用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"}
任何帮帮我? 谢谢。
答
该解决方案为我工作:
甲骨文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存储过程。如果你想要学习这两件事情,没有什么不好的,但是试着只做一件你不知道的事情。这将帮助您识别错误。
在你的代码由三个主要错误:
- 在查询的WHERE子句从
- SELECT INTO之前的工作只能在PL/SQL块,并执行即时不出手
- 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);
调用存储过程仅用于执行标量查询的目的是什么?通常这个动作可以在不使用存储过程的情况下完成!如果您不知道,请查看OracleCommand.ExecuteScalar方法。 http://docs.oracle.com/cd/E11882_01/win.112/e23174/OracleCommandClass。htm#i998581 –
查询只是一个例子,我将查询编辑到了正确的一个。 –
这并不会改变我评论的意义!你看到我发布的文档链接了吗?还有一个简短的例子,显示应该如何完成这些事情。如果您不知道如何在PL/SQL中正确执行动态SQL,那么这不是绝对适合您的情况,这是另一个问题,但尝试将这两件事分开! –