如何使用 ODP.NET 在存储过程中 return 来自 Oracle 动态 SQL 的记录
How to return records from Oracle dynamic SQL in a stored procedure with ODP.NET
我正在尝试弄清楚如何获取存储过程中保存的动态 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"}
有什么帮助吗?
谢谢。
错误说 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
这个解决方案对我有用:
Oracle 程序代码:
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
(未测试)。
要执行该查询,您不需要动态 SQL 也不需要 PL/SQL 存储过程。如果你想学习这两件事没有什么不好,但试着只做一件事你一次不知道。这将有助于您识别错误。
您在代码中犯了三个主要错误:
- 在您的查询中,WHERE 子句位于 FROM
之前
- SELECT INTO 仅在 PL/SQL 块中有效,立即执行不会执行
- DBMS_OUTPUT 如果您不调用 DBMS_OUTPUT.GET_LINES 并且在它工作之前没有做所有需要做的事情,那么 DBMS_OUTPUT 将无法在 .NET 中工作
所以这是您需要以简单正确的方式执行它的 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);
我正在尝试弄清楚如何获取存储过程中保存的动态 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"}
有什么帮助吗? 谢谢。
错误说 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
这个解决方案对我有用:
Oracle 程序代码:
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
(未测试)。
要执行该查询,您不需要动态 SQL 也不需要 PL/SQL 存储过程。如果你想学习这两件事没有什么不好,但试着只做一件事你一次不知道。这将有助于您识别错误。
您在代码中犯了三个主要错误:
- 在您的查询中,WHERE 子句位于 FROM 之前
- SELECT INTO 仅在 PL/SQL 块中有效,立即执行不会执行
- DBMS_OUTPUT 如果您不调用 DBMS_OUTPUT.GET_LINES 并且在它工作之前没有做所有需要做的事情,那么 DBMS_OUTPUT 将无法在 .NET 中工作
所以这是您需要以简单正确的方式执行它的 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);