gpt4 book ai didi

oracle - 使用 ODP.NET 从 PL/SQL 函数获取 RECORD,无需接触 PL/SQL 代码

转载 作者:行者123 更新时间:2023-12-02 08:34:58 24 4
gpt4 key购买 nike

标题非常不言自明:从 C# 应用程序,使用 ODP.NET,我尝试调用一个 PL/SQL 函数,该函数返回的不是一个简单的值,而是一条记录。

不幸的是,我无权添加或更改 PL/SQL 代码,因此尝试将该函数包装在另一个返回不同类型的函数中对我来说不是一个选择。

这是一个简化的示例...

PL/SQL:

CREATE OR REPLACE PACKAGE FOO_PACKAGE AS

TYPE FOO_RECORD IS RECORD (
BAR VARCHAR2(50),
BAZ VARCHAR2(50)
);

FUNCTION FOO_FUNCTION RETURN FOO_RECORD;

END;
/

CREATE OR REPLACE PACKAGE BODY FOO_PACKAGE AS

FUNCTION FOO_FUNCTION RETURN FOO_RECORD AS
R FOO_RECORD;
BEGIN
R.BAR := 'Hello bar!';
R.BAZ := 'Hello baz!';
RETURN R;
END;

END;
/

C#:

我首先尝试的是最直接的方法,但是我不知道如何绑定(bind)返回参数...

using (var conn = new OracleConnection(connection_string)) {
conn.Open();
using (var tran = conn.BeginTransaction()) {
using (var cmd = conn.CreateCommand()) {
cmd.CommandText = "FOO_PACKAGE.FOO_FUNCTION";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(
null,
/* What to use here? */,
ParameterDirection.ReturnValue
);
cmd.ExecuteNonQuery();
}
}
}

我也尝试过一些“迂回”的方法,但它们都会抛出异常:

cmd.CommandText = "SELECT * FROM FOO_PACKAGE.FOO_FUNCTION";
cmd.ExecuteReader(); // ORA-00942: table or view does not exist

cmd.CommandText = "SELECT FOO_PACKAGE.FOO_FUNCTION FROM DUAL";
cmd.ExecuteReader(); // ORA-00902: invalid datatype

cmd.CommandText = "SELECT BAR, BAZ FROM (SELECT FOO_PACKAGE.FOO_FUNCTION FROM DUAL)";
cmd.ExecuteReader(); // ORA-00904: "BAZ": invalid identifier

最佳答案

您需要anonymous PL/SQL block将函数结果转换为另一种表示形式:

declare
vFooRes FOO_PACKAGE.FOO_RECORD;
vRes sys_refcursor;
begin
vFooRes := FOO_PACKAGE.FOO_FUNCTION;
open vRes for select vFooRes.BAR, vFooRes.BAZ from dual;
--:result := vRes;
end;

SQLfiddle

并执行它而不是调用存储过程:

cmd.CommandText = "declare\n" +
" vFooRes FOO_PACKAGE.FOO_RECORD;\n" +
"begin\n" +
" vFooRes := FOO_PACKAGE.FOO_FUNCTION;\n" +
" open :result for select vFooRes.BAR, vFooRes.BAZ from dual;\n" +
"end;";

OracleParameter p = cmd.Parameters.Add(
"result",
OracleDbType.RefCursor,
DBNull.Value,
ParameterDirection.Output
);

cmd.ExecuteNonQuery();

执行cmd后,您会在result参数中获得光标,该参数可用于填充数据集:

var adapter = new OracleDataAdapter(cmd);
var data = new DataSet("FooDataSet");
adapter.Fill(data, "result", (OracleRefCursor)(p.Value));

关于oracle - 使用 ODP.NET 从 PL/SQL 函数获取 RECORD,无需接触 PL/SQL 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16941214/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com