programing

마지막 항목에서 두 번 실행 중인 Oracle 커서

lastmoon 2023. 8. 30. 22:00
반응형

마지막 항목에서 두 번 실행 중인 Oracle 커서

다음 줄을 따라 코드를 사용하여 테이블의 내용을 연결하여 문자열을 만드는 커서 루프가 있습니다.

OPEN cur_t;
LOOP
    FETCH cur_t INTO v_texttoadd;

    v_string := v_string || v_texttoadd;
EXIT WHEN cur_t%notfound;
END LOOP;

물론 문제는 시스템이 더 이상 찾을 것이 없다는 것을 깨닫기 전에 한 번 더 실행되기 때문에 마지막 항목이 두 번 추가된다는 것입니다.

저는 이런 것들을 가지고 놀려고 했습니다.

OPEN cur_t;
WHILE cur_t%found;
LOOP
    FETCH cur_t INTO v_texttoadd;

    v_string := v_string || v_texttoadd;
END LOOP;

하지만 그것은 아무것도 돌려주지 않는 것처럼 보였습니다.

각 행이 결과 문자열에 한 번만 나타나도록 하려면 어떤 구문을 사용해야 합니까?

사용해 볼 수 있습니다.

OPEN cur_t;
LOOP
  FETCH cur_t INTO v_texttoadd;
  EXIT WHEN cur_t%notfound;
  v_string := v_string || v_texttoadd;
END LOOP;

FETCH가 실행될 때 %notfound가 설정되어 있고 더 이상 가져올 행이 없기 때문에 이 작업이 수행됩니다.이 예제에서는 연결 후 %not found를 선택하여 결과적으로 복제를 수행했습니다.

정답은 이미 제시되었지만, 조금 더 자세히 설명할 뿐입니다.

현재 상황 시뮬레이션:

SQL> declare
  2    cursor cur_t
  3    is
  4    select ename
  5      from emp
  6     where deptno = 10
  7    ;
  8    v_texttoadd emp.ename%type;
  9    v_string    varchar2(100);
 10  begin
 11    open cur_t;
 12    loop
 13      fetch cur_t into v_texttoadd;
 14      v_string := v_string || v_texttoadd;
 15      exit when cur_t%notfound;
 16    end loop
 17    ;
 18    dbms_output.put_line(v_string);
 19  end;
 20  /
CLARKKINGMILLERMILLER

PL/SQL-procedure is geslaagd.

여기 Miller는 두 번 인쇄됩니다.EX를 전환하는 것만으로IT 문과 v_string 할당을 통해 원하는 결과를 얻을 수 있습니다.

SQL> declare
  2    cursor cur_t
  3    is
  4    select ename
  5      from emp
  6     where deptno = 10
  7    ;
  8    v_texttoadd emp.ename%type;
  9    v_string    varchar2(100);
 10  begin
 11    open cur_t;
 12    loop
 13      fetch cur_t into v_texttoadd;
 14      exit when cur_t%notfound;
 15      v_string := v_string || v_texttoadd;
 16    end loop
 17    ;
 18    dbms_output.put_line(v_string);
 19  end;
 20  /
CLARKKINGMILLER

PL/SQL-procedure is geslaagd.

그러나 루프에 커서를 사용하면 PL/SQL 코드가 더 쉬워집니다.그런 다음 v_text를 건너뛰어 변수를 추가하면 루프의 줄 수가 줄어듭니다.

SQL> declare
  2    cursor cur_t
  3    is
  4    select ename
  5      from emp
  6     where deptno = 10
  7    ;
  8    v_string    varchar2(100);
  9  begin
 10    for r in cur_t
 11    loop
 12      v_string := v_string || r.ename;
 13    end loop
 14    ;
 15    dbms_output.put_line(v_string);
 16  end;
 17  /
CLARKKINGMILLER

PL/SQL-procedure is geslaagd.

또한 straight SQL을 사용하여 작업을 수행할 수도 있습니다.버전 10g 이상인 경우 SQL 모델 절의 예:

SQL> select string
  2    from ( select string
  3                , rn
  4             from emp
  5            where deptno = 10
  6            model
  7                  dimension by (rownum rn)
  8                  measures (ename, cast(null as varchar2(100)) string)
  9                  ( string[any] order by rn desc = ename[cv()] || string[cv()+1]
 10                  )
 11         )
 12   where rn = 1
 13  /

STRING
-----------------------------------------------------------------------------------
CLARKKINGMILLER

1 rij is geselecteerd.

안녕, 롭.

가져오기가 새 행을 검색하지 못하면 %notfound가 설정됩니다.

다른 가능한 방법(이 방법은 "if"와 "ref when"s를 피함):

OPEN cur_t;
FETCH cur_t INTO v_texttoadd;
WHILE cur_t%found LOOP
    v_string := v_string || v_texttoadd;
    FETCH cur_t INTO v_texttoadd;
END LOOP;

간단한 답변이지만 최선은 아닐 수 있습니다.

OPEN cur_t;
LOOP
    FETCH cur_t INTO v_texttoadd;
    IF cur_t%found THEN
        v_string := v_string || v_texttoadd;
    END IF;
EXIT WHEN cur_t%notfound;
END LOOP;

저는 Microsoft SQL에서 커서 기반 솔루션을 많이 만들었는데, 이 솔루션은 항상 완벽하게 작동했습니다.SQL Server를 너무 많이 돌려받고 싶어요!) 하지만 이 질문에 대한 모든 대답이 잘못된 것으로 판명되었습니다. 그러나 커서의 맨 마지막 행은 그들이 제시한 방법을 아무리 주의 깊게 따르더라도 항상 두 번 실행됩니다.

잠시도 아닌 것은 잊어버리세요.loop그리고 잊어버려요exit이것은 이중 실행을 방지하기 위해 반드시 수행해야 하는 작업입니다(T-SQL에서 수행하는 작업과 거의 같습니다!).

  cursor c_mm is select a, b, c, d from mytable;

  begin
    open c_mm;
    fetch c_mm into a, b, c, d;
    while (not c_mm%notfound) loop 
        -- do what you have to do here

        fetch c_mm into a, b, c, d;
    end loop;
    close c_mm;
  end;

제가 정말 이해할 수 없는 것은 왜 모든 Oracle 기술 자료 기사와 포럼 게시물(및 스택 오버플로)이 이 루프 내의 종료 솔루션을 홍보하는지에 대한 것입니다. 이는 명백히 잘못된 것입니다!

언급URL : https://stackoverflow.com/questions/896319/oracle-cursor-running-through-the-last-item-twice

반응형