【问题标题】:Passing different (multiple) cursors to the same For Loop将不同的(多个)游标传递给同一个 For 循环
【发布时间】:2009-01-27 17:02:05
【问题描述】:

为更好地澄清而编辑:


2009 年 1 月 28 日添加:为了便于解释,我过度简化了代码,但是 select 语句很长很复杂,第二个依赖于第一个游标完成并循环后的第一个含义通过并创建插入,第二个选择实际上将第一个插入视为 where 子句的一部分。

这就是为什么我需要多次使用循环而不以任何方式组合选择。 当我按照我想要调用它们的顺序调用它们时,我需要它们运行,这让我回到了我原来的问题,是否可以重新使用具有不同光标的循环?

再次感谢。


我正在创建一个包 (Oracle 10),其中有 4 个不同的选择语句(可能还会有更多),我为所有这些语句创建了一个游标并获取我的数据。现在通常我会获取数据并创建一个 For 循环,一切都很好。

我的问题是我有 4 个不同的选择,但我想重新使用循环,以便我可以让光标 c2 使用相同的循环以及 c3 和 c4。所有这些都是游标从非常不同的选择中获取不同的信息,但它们都进入同一个表,我的插入语句在循环中。此外,我不能将所有选择连接在一起,它们必须在每个循环后按顺序完成

我在下面创建了一个带有 4 个循环的示例,但正如您所见,它们都是相同的,唯一的区别是:对于 r 在 c1 循环中,对于 r 在 c2 循环中...... 我认为必须有某种方法可以重用循环。我有一些想法,但都没有奏效。

 cursor c1 is  select info_a, info_b from table_x where info_g = 77; 
 cursor c2 is  select info-a, info_b from table_x where info_g = 88;
 cursor c3 is  select info-a, info_b from table_y where info_j = 88;
 cursor c4 is  select info-a, info_b from table_y where info_j = 99;


  Begin

     For r in c1 loop
        insert into fun_table (good_info, boring_info) values (r.info_a, r.info-b);
     end loop;
    commit;

     For r in c2 loop
        insert into fun_table (good_info, boring_info) values (r.info_a, r.info-b);
     end loop;
    commit;

     For r in c3 loop
        insert into fun_table (good_info, boring_info) values (r.info_a, r.info-b);
     end loop;
    commit;

     For r in c4 loop
        insert into fun_table (good_info, boring_info) values (r.info_a, r.info-b);
     end loop;
    commit;

   end;

希望这更有意义,谢谢

我进行了编辑,然后出现了一些答案……抱歉。 原来的样子是这样的:

 cursor c1 is  select some_info, other_info from some_table where where some_thing = 'xyz'; 
cursor c2 is select some_info, other_info from some_table where where some_thing = 'abc';

   For r in c1 loop
        insert into fun_table (good_info, boring_info) values (r.some_info, r.other_info);
    end loop;

【问题讨论】:

  • 请发布您希望如何查看它(也许一些无法编译但让我们了解您想要什么的代码)
  • 在 for 循环中: For r in c1 loop where it uses c1 我想传入任何游标,因此它可以是: For r in c2 loop or : For r in d1 loop or any set要循环的数据
  • 你能展示不同的SQL吗?
  • 为什么插入时需要游标?只需使用 insert...select... 语句。思考基于集合而不是基于行。

标签: sql oracle oracle10g


【解决方案1】:

或者干脆做:

cursor c1 is  
select info_a, info_b from table_x where info_g IN (77, 88) UNION ALL
select info-a, info_b from table_y where info_j IN (88, 99);

Begin

     For r in c1 loop
        insert into fun_table (good_info, boring_info) values (r.info_a, r.info-b);
     end loop;
    commit;

END;

【讨论】:

    【解决方案2】:

    如果有人需要知道如何做到这一点,这是一个有效的答案。 我办公室的另一个做过一些研究的人给我的:

    我创建了一个包含 2 个程序的包 第一个是多个游标,第二个是循环 (我过度简化了选择和插入以显示它是如何完成的)

    第一个过程称为 Select_Cursor :

    procedure Select_Cursors is 
    
      the_cursor sys_refcursor;    -- this defines the_cursor as type sys_refcursor  
    
    begin
    
     open the_cursor for 
    
         select  application_idn, account_idn     
          from accounts ac,  applications ha
         where  something = somethingelse
    
     Insert_Cursor ( the_cursor );  
     close the_cursor;
    
      open the_cursor for 
    
         select  application_idn, account_idn     
          from accounts ac,  applications ha
         where  somethingfunny = somethingcrazy
    
      Insert_Cursor ( the_cursor );  
     close the_cursor;
    
    
     ...  repeat for every select
    
     end Select_Cursors; 
    

    名为 Insert_Cursor 的第二个过程是:

    procedure Insert_Cursor ( p_cursor in sys_refcursor ) is
    
    
        begin
    
           loop
                fetch p_cursor into  application_idn, account_idn ;
                exit when p_cursor%notfound;
    
                insert into payments (issue_type_des, issued_amt, payment_Type_cde,payment_Status_Cde, created_by, application_idn, account_idn)
                     values          (v_paytype, v_amount, 'S','PE','This Process',  application_idn, account_idn);
           end loop;
    
           commit;
    
        end Insert_Cursor;
    

    再次感谢所有给出答案并调查问题的人,不胜感激

    【讨论】:

      【解决方案3】:

      所以你将有以下选择语句:

      select some_info, other_info from some_table where some_thing = 'xyz'; 
      select c2_info, c2_other from c2_table where c2_thing = 'XYZ;'
      

      您可以通过将 c1 声明为其他未知类型的 SYS_REFCURSOR 来做到这一点,并确保每个查询的所有列都属于相同类型(或接近它)。您不能使用行类型,您必须单独声明列,并且是适用于所有查询的通用类型。但以下确实有效。

      DECLARE
        C1 SYS_REFCURSOR;
        TableID NUMBER;
        TableName VARCHAR2(240);
      BEGIN
      
        OPEN C1 FOR select CALENDAR_ID, CALENDAR_NAME from CALENDARS;
      
        LOOP
          FETCH C1 INTO tableid, tablename;
          EXIT WHEN C1%NOTFOUND;
          DBMS_OUTPUT.put_line ('ID: ' || to_char(tableID) || ' -- NAME: ' || TableName);
        END LOOP;
        CLOSE C1;
        OPEN C1 for SELECT INIT_ID, NAME FROM INITS;  
        LOOP
          FETCH C1 INTO tableid, tablename;
          EXIT WHEN C1%NOTFOUND;
          DBMS_OUTPUT.put_line ('ID: ' || to_char(tableID) || ' -- NAME: ' || TableName);
        END LOOP;
        CLOSE C1;
      END;
      

      【讨论】:

        【解决方案4】:

        只要做:

        begin
          insert into cool_table 
          ( neat_info 
          , boring_info)
          select some_info
          ,      other_info 
          from some_table 
          where some_thing = 'XYZ';
        end;
        

        不需要游标循环。

        【讨论】:

          【解决方案5】:

          为什么不动态构建游标查询并且只使用一个游标?

          我假设 77、88 和 99 来自存储过程的参数。

          cursor c1 is  
          select info_a, info_b from table_x where info_g in( 77, 88)
          UNION
          select info-a, info_b from table_y where info_j in (88, 99)
          ...
          

          【讨论】:

            猜你喜欢
            • 2012-08-28
            • 2017-11-14
            • 2021-07-27
            • 2018-10-15
            • 2021-10-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-03-12
            相关资源
            最近更新 更多