Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle 在pl/sql for循环中是否有其他方法来表示“下一步”?_Oracle_Plsql_Controls_For Loop - Fatal编程技术网

Oracle 在pl/sql for循环中是否有其他方法来表示“下一步”?

Oracle 在pl/sql for循环中是否有其他方法来表示“下一步”?,oracle,plsql,controls,for-loop,Oracle,Plsql,Controls,For Loop,所以我有一个for循环,它处理ID列表,并且有一些相当复杂的事情要做。不谈所有丑陋的细节,基本上是这样的: DECLARE l_selected APEX_APPLICATION_GLOBAL.VC_ARR2; ...snip... BEGIN -- get the list ids l_selected := APEX_UTIL.STRING_TO_TABLE(:P4_SELECT_LIST); -- process ea

所以我有一个for循环,它处理ID列表,并且有一些相当复杂的事情要做。不谈所有丑陋的细节,基本上是这样的:

DECLARE l_selected APEX_APPLICATION_GLOBAL.VC_ARR2; ...snip... BEGIN -- get the list ids l_selected := APEX_UTIL.STRING_TO_TABLE(:P4_SELECT_LIST); -- process each in a nice loop FOR i IN 1..l_selected.count LOOP -- do some data checking stuff... -- here we will look for duplicate entries, so we can noop if duplicate is found BEGIN SELECT county_id INTO v_dup_check FROM org_county_accountable WHERE organization_id = :P4_ID AND county_id = v_county_id; -- NEXT;! NOOP;! but there is no next! EXCEPTION WHEN NO_DATA_FOUND THEN dbms_output.put_line('no dups found, proceeding'); END; -- here we have code we only want to execute if there are no dupes already IF v_dup_check IS NULL THEN -- if not a duplicate record, proceed... ELSE -- reset duplicate check variable v_dup_check := NULL; END; END LOOP; END; 我通常是通过选择一个值来处理这个问题的,然后将下面的代码包装在IF语句检查中,以确保重复检查变量为NULL。但这很烦人。我只想说下一句话;或NOOP;或者别的什么。特别是因为我已经捕获了NO_DATA_FOUND异常。我想我可以给甲骨文写封信,但我很好奇其他人是怎么处理的


我也可以将其包装到函数中,但我正在寻找更干净/更简单的东西。

在这种情况下,GOTO语句可能会很有用。请参阅控制结构中的,以了解如何执行此操作。此外,您可能希望在此处搜索,以了解如何查询记录的存在性。运行查询并等待异常不是最佳选择。

与其捕获未找到的数据,不如选择变量中匹配项的数量,比如l\u count,然后在该计数为零时继续?如下所示:

DECLARE l_selected APEX_APPLICATION_GLOBAL.VC_ARR2; l_count INTEGER; ...snip... BEGIN -- get the list ids l_selected := APEX_UTIL.STRING_TO_TABLE(:P4_SELECT_LIST); -- process each in a nice loop FOR i IN 1..l_selected.count LOOP -- do some data checking stuff... -- here we will count duplicate entries, so we can noop if duplicate is found SELECT COUNT(*) INTO l_count FROM org_county_accountable WHERE organization_id = :P4_ID AND county_id = v_county_id; IF l_count = 0 THEN -- here we have code we only want to execute if there are no dupes already -- if not a duplicate record, proceed... END IF; END LOOP; END;
Oracle11g在PL/SQL中添加了一个C风格的continue循环构造,从语法上讲,这听起来就像您正在寻找的

出于您的目的,为什么不在进入循环之前消除重复项呢?这可以通过使用表函数查询l_selected来完成,然后过滤掉您不想要的记录,而不是迭代每个值。类似于

declare

l_selected APEX_APPLICATION_GLOBAL.VC_ARR2;

cursor no_dups_cur (p_selected APEX_APPLICATION_GLOBAL.VC_ARR2) is 
  select * from (
  select selected.*, 
         count(*) over (partition by county_id) cnt -- analytic to find counts grouped by county_id
    from table(p_selected) selected -- use table function to treat VC_ARR2 like a table 
    ) where cnt = 1 -- remove records that have duplicate county_ids
    ;

begin

l_selected := APEX_UTIL.STRING_TO_TABLE(:P4_SELECT_LIST);

for i in no_dups_cur(l_selected) loop

  null; -- do whatever to non-duplicates 

end loop;

end;

只需将确定重复的逻辑替换为您自己的,您的示例中没有足够的信息来真正回答该部分

也可以计算行数,请参见Pourquoi Litytestdata,但您也可以在when_no_data_found exception块中执行您想要执行的操作


另一种方法-将支票转换为本地函数:

DECLARE
  l_selected APEX_APPLICATION_GLOBAL.VC_ARR2;

  ...snip...
  FUNCTION dup_exists 
     ( p_org_id org_county_accountable.organization_id%TYPE
     , p_county_id org_county_accountable.county_id%TYPE
     ) RETURN BOOLEAN 
  IS
    v_dup_check org_county_accountable.county_id%TYPE;
  BEGIN
    SELECT county_id INTO v_dup_check FROM org_county_accountable
    WHERE organization_id = p_org_id AND county_id = p_county_id;
    RETURN TRUE;
  EXCEPTION WHEN NO_DATA_FOUND THEN
    RETURN FALSE;
  END;
BEGIN

  -- get the list ids
  l_selected := APEX_UTIL.STRING_TO_TABLE(:P4_SELECT_LIST);
  -- process each in a nice loop
  FOR i IN 1..l_selected.count
  LOOP
    -- do some data checking stuff...

    -- here we have code we only want to execute if there are no dupes already
    IF NOT dup_exists (:P4_ID, v_county_id) THEN
      -- if not a duplicate record, proceed...

    END;
  END LOOP;
END;
当然,如果您愿意,可以重新编写本地函数以使用count方法:

  FUNCTION dup_exists 
     ( p_org_id org_county_accountable.organization_id%TYPE
     , p_county_id org_county_accountable.county_id%TYPE
     ) RETURN BOOLEAN 
  IS
    l_count INTEGER;
  BEGIN
     SELECT COUNT(*) INTO l_count 
       FROM org_county_accountable
      WHERE organization_id = p_org_id AND county_id = p_county_id;
     RETURN (l_count > 0);
  END;

另一种方法是引发和处理用户定义的异常:

DECLARE
  l_selected APEX_APPLICATION_GLOBAL.VC_ARR2;
  duplicate_org_county EXCEPTION;

  ...snip...
BEGIN

  -- get the list ids
  l_selected := APEX_UTIL.STRING_TO_TABLE(:P4_SELECT_LIST);
  -- process each in a nice loop
  FOR i IN 1..l_selected.count 
  LOOP
    BEGIN
      -- do some data checking stuff...

      -- here we will look for duplicate entries, so we can noop if duplicate is found
      BEGIN
        SELECT county_id INTO v_dup_check FROM org_county_accountable
        WHERE organization_id = :P4_ID AND county_id = v_county_id;
        RAISE duplicate_org_county;
      EXCEPTION WHEN NO_DATA_FOUND THEN
        dbms_output.put_line('no dups found, proceeding');
      END;
      -- here we have code we only want to execute if there are no dupes already

    EXCEPTION
      WHEN duplicate_org_county THEN NULL;
    END;
  END LOOP;
END;

我通常不会这样做,但如果有六个理由跳转到下一条记录,这可能比多个嵌套的IFs更好。

我知道这是一个老生常谈,但我忍不住注意到上面的答案都没有考虑光标:

<xmp>
<<next_loop>>
loop
...
...
if ....
then
   goto next_loop;

</xmp>
有四个与游标关联的属性:ISOPEN、FOUND、NOTFOUND和ROWCOUNT。可以使用%分隔符访问这些属性,以获取有关光标状态的信息

游标属性的语法为:

cursor_name%attribute
其中cursor_name是显式游标的名称

因此,在本例中,您可以使用ROWCOUNT,它指示到目前为止为您的目的获取的行数,如下所示:

declare 
   aux number(10) := 0;
   CURSOR cursor_name is select * from table where something;
begin
     select count(*) into aux from table where something;
     FOR row IN cursor_name LOOP
        IF(aux > cursor_name%ROWCOUNT) THEN 'do something is not over';
        ELSE 'do something else';
        END IF;
     END LOOP;
end;

我正要写同样的东西很高兴看到其他人使用APEX!顶点岩石,伙计;-forums.oracle.com上的论坛真的很有帮助。在您的问题以及tuinstoel和Pourqoi的解决方案中,您在FOR循环的每个迭代中都执行额外的SQL查询和从PL/SQL到/从PL/SQL的上下文切换……这不一定便宜。如果性能是一个问题,最好在一个查询中提前删除所有DUP。jimmyorr,这是一个非常好的观点,先生。这实际上是一个非常紧凑的解决方案,GOTO声明,谢谢!我不太明白你剩下的答案。我非常乐意查询重复记录,这是必要的。不过,我更喜欢选择一个计数的想法,因为没有抛出异常。
declare 
   aux number(10) := 0;
   CURSOR cursor_name is select * from table where something;
begin
     select count(*) into aux from table where something;
     FOR row IN cursor_name LOOP
        IF(aux > cursor_name%ROWCOUNT) THEN 'do something is not over';
        ELSE 'do something else';
        END IF;
     END LOOP;
end;