문제

그래서 ID 목록을 처리하고 상당히 복잡한 작업을 수행하는 for 루프가 있습니다.모든 추악한 세부 사항을 다루지 않고 기본적으로 다음과 같습니다.

    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인지 확인하는 것입니다.하지만 짜증난다.나는 단지 NEXT라고 말할 수 있기를 원합니다.또는 NOOP;또는 뭔가.특히 NO_DATA_FOUND 예외를 이미 잡아야 하기 때문에 더욱 그렇습니다.오라클에 편지를 쓸 수 있을 것 같은데, 다른 사람들은 이를 어떻게 처리하는지 궁금합니다.

이것을 함수로 래핑할 수도 있지만 좀 더 깨끗하고 간단한 것을 찾고 있었습니다.

도움이 되었습니까?

해결책

행 수를 계산하는 것도 가능합니다(Pourquoi Litytestdata 참조). when_no_data_found exception 차단하다.

declare 
  l_selected    apex_application_global.vc_arr2;
  l_county_id   org_county_accountable.count_id%type;
begin
  l_selected := apex_util.string_to_table(:p4_select_lst);
  for i in l_selected.first..l_selected.last loop
    begin
      select count_id
      into   l_county_id
      from   org_county_accountable
      where  organization_id = :p4_id
      and    county_id       = v_county_id;
    exception
      when no_data_found then 
        -- here we have code we only want to execute if there are no dupes already
        -- if not a duplicate record, proceed...
    end;
  end loop;
end;

다른 팁

Oracle 11g는 PL/SQL에 C 스타일의 "계속" 루프 구성을 추가했는데, 이는 구문적으로 사용자가 찾고 있는 것과 유사합니다.

귀하의 목적을 위해 루프에 들어가기 전에 중복 항목을 제거하는 것이 어떻습니까?이는 테이블 함수를 사용하여 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;

"중복"을 결정하기 위한 논리를 자신의 논리로 대체하십시오(예제에서 해당 부분에 실제로 답변할 정보가 충분하지 않았습니다).

잡는 대신 NO_DATA_FOUND, 일치하는 항목 수를 변수로 선택하는 것은 어떻습니까? l_count, 이 개수가 0이 되면 계속 진행하시겠습니까?다음과 같은 것 :

    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;
<xmp>
<<next_loop>>
loop
...
...
if ....
then
   goto next_loop;

</xmp>

GOTO문을 사용한 경우입니다. ~할 것 같다 유용한.참조 오라클 문서 제어 구조에서 이를 수행하는 방법을 확인하십시오.또한 이곳저곳을 검색해 보시면 레코드 존재 여부를 쿼리하는 방법을 알아보실 수 있습니다.쿼리를 실행하고 예외를 기다리는 것은 최적이 아닙니다.

또 다른 방법 - 수표를 로컬 기능으로 전환합니다.

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;

일반적으로 이 작업을 수행하지 않지만 다음 레코드로 이동해야 할 이유가 6가지 정도 있는 경우 여러 중첩 IF보다 이 방법이 더 나을 수 있습니다.

나는 이것이 오래된 것이라는 것을 알고 있지만 위의 답변 중 어느 것도 커서를 고려하지 않는다는 것을 알 수 없었습니다. 속성:

커서와 관련된 네 가지 속성은 다음과 같습니다.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;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top