创建带有 2 个游标、一个参数并从表中给出结果的 PL/SQL 脚本?

Posted

技术标签:

【中文标题】创建带有 2 个游标、一个参数并从表中给出结果的 PL/SQL 脚本?【英文标题】:Create PL/SQL script with 2 cursors, a parameter and give results from a table? 【发布时间】:2014-09-15 21:32:20 【问题描述】:

我需要创建一个脚本,从表 A 中放入一个键号(稍后将用作参数),然后将该参数或键号流入查询中,然后将这些结果转储到保存记录或表中后来的操纵等等。因为每次提取有超过 1 行(实际上每个查询结果或每个声明键有 6 行),我决定使用 Bulk Collect 子句。虽然我在不同数据库上的初始测试有效,但我还没有弄清楚为什么真正的脚本不工作。

这是我使用的测试脚本:

DECLARE

--Cursors--
CURSOR prod_id is select distinct(product_id) from product order by 1 asc;

CURSOR cursorValue(p_product_id NUMBER) IS
        SELECT h.product_description,o.company_short_name
        FROM company o,product h
        WHERE o.product_id =h.product_id
        AND h.product_id =p_product_id
        AND h.product_id IS NOT NULL
        ORDER by 2;

    --Table to store Cursor data--        
    TYPE indx IS TABLE OF cursorValue%ROWTYPE
    INDEX BY PLS_INTEGER;
    indx_tab  indx;

    ---Variable objects---
    TotalIDs PLS_INTEGER;
    TotalRows PLS_INTEGER := 0 ;

BEGIN
      --PARAMETER CURSOR RUNS---
    FOR prod_id2 in prod_id LOOP
    dbms_output.put_line('Product ID: ' || prod_id2.product_id);
    TotalIDs := prod_id%ROWCOUNT;

          --FLOW PARAMETER TO SECOND CURSOR--
        Open cursorValue(prod_id2.product_id);
        Loop 
        Fetch cursorValue Bulk collect into indx_tab;

          ---data dump into table---
        --dbms_output.put_line('PROD Description: ' || indx_tab.product_description|| ' ' ||'Company Name'|| indx_tab.company_short_name);
        TotalRows := TotalRows + cursorValue%ROWCOUNT;
        EXIT WHEN cursorValue%NOTFOUND;
        End Loop;
        CLOSE cursorValue;
    End Loop;    
dbms_output.put_line('Product ID Total: ' || TotalIDs);
dbms_output.put_line('Description Rows: ' || TotalRows);
END;


Test Script Results:
anonymous block completed
Product ID: 1
Product ID: 2
Product ID: 3
Product ID: 4
Product ID: 5
Product ID Total: 5
Description Rows: 6

更新:将问题标记为“已回答”谢谢。

【问题讨论】:

你问了几个问题,有点,但我已经回答了似乎最紧迫的问题。由于您的测试块有效,您似乎已经知道如何使用批量收集(尽管您似乎已经删除了loop,也许没有将其注释掉)。我不确定一旦错字被修复,你是否还有其他问题,但如果是这样,你应该问一个单独的问题,显示你的真实块的当前和期望的行为。 dbms_output 应该只真正用于基本调试,因为客户端可能不会显示输出 - 虽然不确定你想对数据做什么。 所以拼写正确(感谢我最初没有看到它)。以下是现在的错误: 错误报告:ORA-06550:第 41 行,第 43 列:PLS-00302:必须声明组件“CLAIM_NUM” ORA-06550:第 41 行,第 11 列:PL/SQL:忽略 SQL 语句06550. 00000 - “行 %s,列 %s:\n%s” *原因:通常是 PL/SQL 编译错误。 *行动: 基本上,我希望将第二个游标批量中的行(多个)收集到一个表中,以便案例语句可以引用表中的列。 嗯,第 41 行指的是CUR_CLAIMNUM2.CLAIM_NUM;但光标正在选择CLAIM_NO。这是完全一样的错误。抱歉,但这确实是基本调试 - 查看错误,找到代码中的行号,查找错误文本描述的内容... 按照建议,我仔细查看了代码并进行了几处更改(也根据建议),没有任何错误。问题仍然存在,我是否需要声明一条与表的第二个游标具有相同 %ROWTYPE 的记录以显示列? : 【参考方案1】:

第 7 行出现第一个错误。在第 4 行,您有:

  CURSOR CUR_CLAIMNUM IS
                      SELECT DISTINCT(CLAIM_NO)FROM R7_OPENCLAIMS;

... 这似乎是有效的,所以您的列名是CLAIM_NO。第 7 行:

  CURSOR OPEN_CLAIMS (CLAIM_NUM  R7_OPENCLAIMS.CLAIM_NUM%TYPE)  IS

...所以您将列名输入错误为CLAIM_NUM,该表中不存在该列名。这是错误消息告诉你的,真的。

其他错误是因为光标无效,因为那个错字。

当你打开第二个游标时你有同名混淆:

          OPEN OPEN_CLAIMS (CUR_CLAIMNUM2.CLAIM_NUM);

... 失败,因为游标查询的是CLAIMNO 而不是CLAIMNUM;除了这里,distinct 进一步混淆了它。您没有为列名起别名,因此 Oracle 应用了一个,您可以参考,但添加您自己的更简单:

  CURSOR CUR_CLAIMNUM IS
                      SELECT DISTINCT(CLAIM_NO) AS CLAIM_NO FROM R7_OPENCLAIMS;

然后

          OPEN OPEN_CLAIMS (CUR_CLAIMNUM2.CLAIM_NO);

但我建议您在定义和循环声明中也将光标名称从 CUR_CLAIMNUM 更改为 CUR_CLAIM_NO。并且拥有名为CUR_CLAIMNUM2 的游标迭代器很奇怪,因为它表明它本身就是一个游标名称;也许像ROW_CLAIM_NO 这样的东西会更清楚。

【讨论】:

以上是关于创建带有 2 个游标、一个参数并从表中给出结果的 PL/SQL 脚本?的主要内容,如果未能解决你的问题,请参考以下文章

BULK 收集和 FORALL 两次插入数据

oracle 游标分析与理解(基础)

在其他两个游标中找到游标时如何从表中删除

仅拥有最新数据并从表中删除其余数据的有效方法

从表中选择数据并从另一个表中填充特定值

请教大虾们,反复执行同一个游标(cursor),每次从表中取出1000条,直到将表中的数据取完;