마지막 항목에서 두 번 실행 중인 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
'programing' 카테고리의 다른 글
노드 Js 서버의 터미널에서 demon 명령이 인식되지 않습니다. (0) | 2023.09.04 |
---|---|
커뮤니케이션예외:연결이 실패했을 때 응용 프로그램이 결과를 스트리밍하고 있었습니다.서버에서 'net_write_timeout' 값을 올리는 것을 고려합니다. (0) | 2023.08.30 |
Node.js가 만든 웹 사이트를 Github Pages에 게시하는 방법은 무엇입니까? (0) | 2023.08.30 |
기존 도커 컨테이너에서 명령을 실행하려면 어떻게 해야 합니까? (0) | 2023.08.30 |
활동 제목이 아닌 시작 프로그램에 대해 다른 레이블을 설정하는 방법은 무엇입니까? (0) | 2023.08.30 |