【问题标题】:How can I get result set from Oracle PL/SQL?如何从 Oracle PL/SQL 获取结果集?
【发布时间】:2018-10-30 20:46:18
【问题描述】:

我有一张下表:

CREATE TABLE jun_t AS
SELECT 1 seq, -2000 amt FROM dual
UNION ALL SELECT 2, 4000 FROM dual
UNION ALL SELECT 3, -5000 FROM dual
UNION ALL SELECT 4, -2000 FROM dual
UNION ALL SELECT 5, 3000 FROM dual
UNION ALL SELECT 6, 1500 FROM dual
UNION ALL SELECT 7, -250 FROM dual
UNION ALL SELECT 8, 320 FROM dual
UNION ALL SELECT 9, -4000 FROM dual
UNION ALL SELECT 10, 10000 FROM dual
UNION ALL SELECT 11, -20000 FROM dual;

而且我有事要做,所以我在下面创建并执行了一个 pl/sql 程序:

DECLARE

    CURSOR csr is
    select seq, amt
    from jun_t;

    rec csr%ROWTYPE;
    total jun_t.amt%TYPE;

BEGIN

    OPEN csr;

    total := 0;
    LOOP
        FETCH csr into rec;
        EXIT WHEN csr%NOTFOUND;

        IF (rec.amt + total) > 0 THEN
            total := rec.amt + total;
        ELSE
            total := 0;
        END IF;

        dbms_output.put_line(rec.seq || ',' || rec.amt || ',' || total);

    END LOOP;

END;

结果是这样的:

1,-2000,0
2,4000,4000
3,-5000,0
4,-2000,0
5,3000,3000
6,1500,4500
7,-250,4250
8,320,4570
9,-4000,570
10,10000,10570
11,-20000,0

问题是这样的。我想在我的 c# 应用程序中使用这个结果集,但我找不到方法……我看到了一个使用 ref 游标的示例代码,但在这种情况下似乎不起作用。

我想用这段代码做一个存储过程。

请有人教我一个解决它的方法,或者告诉我我应该学习什么。

谢谢。

【问题讨论】:

  • 您打算使用匿名块还是调用存储过程?
  • 我打算使用存储过程。抱歉,我的问题缺乏细节。
  • 在这种情况下,请注意 Oracle 允许您将表作为存储过程的参数(很像任何其他类型),并且您可以将参数定义为 INOUT。因此,您在调用程序中创建一个空表,将其传递给存储过程,然后将其返回到您的(调用)代码中,其中包含所有值。

标签: c# oracle plsql resultset


【解决方案1】:

您可以将其转换为返回游标的存储过程。但是摆脱 PL/SQL 并使用简单的 SQL 查询要容易得多:

SELECT seq, amt
FROM jun_t;

然后用 C# 计算总数。如果需要,也可以在 C# 中执行转换为单个逗号分隔的行。这比在两个地方管理代码和使用引用游标要容易得多。

顺便说一句:OPEN cursor / LOOP / FETCH INTO / EXIT WHEN 模式已经完全过时了。

【讨论】:

  • 谢谢。你能告诉我'BTW'的原因吗?我是甲骨文的新手,所以我很好奇。
  • 写FOR rec IN (SELECT seq, amt FROM jun_t) LOOP ...do..something..with..rec... END LOOP;更短更容易。并且不能忘记关闭光标。
【解决方案2】:

您可以从单个 sql 查询中获得所需的输出并传递输出参考游标。 FETCH 这个CURSOR 在你的 C# 代码中。

CREATE OR REPLACE PROCEDURE pr_get_total ( p_csr OUT SYS_REFCURSOR )
AS
BEGIN

OPEN p_csr FOR
WITH cte(seq, amt, total) 
     AS (SELECT 0 seq, 
                0 amt, 
                0 total 
         FROM   dual 
         UNION ALL 
         SELECT j.seq AS  seq, 
                j.amt, 
                CASE 
                  WHEN j.amt + total < 0 THEN 0 
                  ELSE j.amt + total 
                END   AS total 
         FROM   jun_t j 
                join cte c 
                  ON j.seq = c.seq + 1) 
SELECT * 
FROM   cte WHERE seq > 0;

END;
/

Demo

注意:这可能比从简单游标 select * from yourtable 获取后逐条计算总和要快,尤其是对于大型数据集。

【讨论】:

  • 非常感谢。你看起来像神谕大师。不,你是神谕。但似乎在 oracle 10g 中不起作用。 oracle 10g版有没有办法解决这个问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-07
  • 1970-01-01
  • 2023-02-23
  • 2011-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多