将基于 CTE 的游标传递给应用程序时,.NET Oracle SP 调用错误 ORA-00604 和 ORA-01001

发布于 2025-01-02 05:24:28 字数 1143 浏览 3 评论 0原文

SP如下: SP代码

调用它的C#代码:C# 代码(这是更新 #3 中描述的更改后的版本)

使用 System.Data.OracleClient、.NET 3.5 SP1、Oracle Express 11g,Windows 7 x64。

这在 SQL Developer(2,3) 中执行得很好。但是,当从 .NET 调用时,会发生这种情况:(请参阅更新 3)

更新 1: 当游标参数读取全局临时值时,使用带有 2 个 OUT 参数的 ExecuteReader 有效 。表与常规表连接。此外,这最终必须在只能使用 ExecuteReader 的 ORM (Lightspeed) 内工作。

更新 2: 看起来 SQL Developer 内部也发生了同样的事情。我用这个:

LOOP
  FETCH results INTO v_rec;
  EXIT WHEN results%notfound;
  DBMS_OUTPUT.PUT_LINE(v_rec.name);
END LOOP;

...来获取“结果”的内容:在SP中工作,并在调用SP的PL/SQL块中使用时产生ORA-01001(当然,在删除SP内的相同代码之后) 。

更新3:将“results1”转换为OUT参数解决了SQL Developer中的问题,显然是游标在超出范围时自动关闭。但是,.NET 现在出现了问题:

ORA-00604: error occurred at recursive SQL level 1
ORA-01059: parse expected before a bind or execute

请参阅 C# 代码 了解参数。尝试了 ExecuteReader、ExecuteNonQuery 和 ExecuteOracleNonQuery 方法,但无济于事。

The SP is as follows: SP code

C# code calling it: C# code (this is the version after making changes described in update #3)

Using System.Data.OracleClient, .NET 3.5 SP1, Oracle Express 11g, Windows 7 x64.

This executes fine in SQL Developer(2,3). However, when calling from .NET, this happens: (see update 3)

Update 1: Using ExecuteReader with 2 OUT parameters works, when the cursor parameter is reading a global temp. table joined with a regular table. Also, this will eventually have to work inside an ORM (Lightspeed) which can only use ExecuteReader.

Update 2: Looks like same thing happens inside SQL Developer. I used this:

LOOP
  FETCH results INTO v_rec;
  EXIT WHEN results%notfound;
  DBMS_OUTPUT.PUT_LINE(v_rec.name);
END LOOP;

... to fetch the contents of "results": works in the SP, and produces ORA-01001 when used in the PL/SQL block calling the SP (after removing the same code inside the SP, of course).

Update 3: Turning "results1" into an OUT parameter solved the problem in SQL Developer, which apparently was cursor being automatically closed when going out of scope. However, .NET now barfs:

ORA-00604: error occurred at recursive SQL level 1
ORA-01059: parse expected before a bind or execute

See C# code for parameters. Tried ExecuteReader, ExecuteNonQuery and ExecuteOracleNonQuery methods, to no avail.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

时间海 2025-01-09 05:24:28

我不是 System.Data.OracleClient 类的专家,因为我通常使用 Oracle 的 ODP.NET。所以我只能给你一些提示:

通常,当你有一个Oracle存储过程时,你会调用ExecuteNonQuery而不是ExecuteReader,因为Oracle从不直接从存储过程返回结果集。存储过程。如果您有一个 CURSOR 类型的 OUT 参数,则使用 ExecuteReader 可能会起作用。但你有两个。

在任何情况下,应该有效的是调用ExecuteNonQuery,然后检索OUT参数:

int totalNumRows = (int)command.Parameters["total_num_rows"].Value;

using (var reader = (OracleDataReader)cmd.Parameters["results"].Value)
{
    while (reader.Read())
    {
        temp.Add(new Blah { Name = (string)reader["name"] });
    }
}

PS System.Data.OracleClient 类已被弃用。

I'm not an expert on the System.Data.OracleClient classes since I usually use Oracle's ODP.NET. So I can only give you some hints:

Typically, when you have an Oracle stored procedure., you call ExecuteNonQuery instead of ExecuteReader since Oracle never directly returns a result set from a stored procedure. Using ExecuteReader might work if you have a single OUT paramter of type CURSOR. But you have two of them.

What should work in any case, is to call ExecuteNonQuery and then retrieve the OUT parameters:

int totalNumRows = (int)command.Parameters["total_num_rows"].Value;

using (var reader = (OracleDataReader)cmd.Parameters["results"].Value)
{
    while (reader.Read())
    {
        temp.Add(new Blah { Name = (string)reader["name"] });
    }
}

P.S. The System.Data.OracleClient classes are deprected.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文