2009-05-22 5 views
7

I가이 라인을 따라 코드를 사용하여, 함께 테이블의 내용을 연결하여 문자열을 구축하는 것 AA 커서 루프 :오라클 커서 두 번

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; 

처럼 뭔가 장난하려하지만 전혀 아무것도 반환하는 것 같지 않았어요.

각 행을 결과 문자열에만 한 번만 표시하려면 어떤 종류의 구문을 사용해야합니까?

답변

21

이 작업을 시도 할 수 있습니다 : %의 NOTFOUND 실행 FETCH 때 설정하고 가져올 더 이상 행이하지 않기 때문에

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

이 작동합니다. 귀하의 예제에서 연결 후 % notfound를 검사 했으므로 결과적으로 중복이있었습니다.

+0

제게 적합하지 않았습니다. 네가 신경 쓰면 내 대답 좀 봐. –

0

간단한 대답은, 가장 가능성이 아니지만 :

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; 
+0

나는 들여 쓰기를 기반으로 EXIT 문이 LOOP 구문의 일부이며 루프 끝 부분에 있어야한다고 가정합니다. 이것은 사실이 아닙니다. EXIT는 루프의 본문에있는 다른 구문과 마찬가지입니다. 이것이 다른 사람들이 보여 주듯이, 문제를 해결하기 위해 퇴거 직후에 놓을 수있는 이유입니다. –

+0

제게 적합하지 않았습니다. 네가 신경 쓰면 내 대답 좀 봐. –

2

퍼센트의 NOTFOUND가 가져올 때 설정에 새 행을 검색하는 데 실패합니다.

또 다른 가능한 방법 (이하 "만약"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; 
+0

여기가 정답 일뿐입니다! –

3

정답은 이미 주어졌다, 그러나 조금을 정교화했다. MILLER 두 번 인쇄 여기

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. 

:

현재의 상황을 시뮬레이션. 커서를 위해 루프를 사용하는 경우

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 코드가 쉬워집니다 : 바로 EXIT 문 및 v_string 할당을 전환하면 원하는 결과를 얻을. 그런 다음 루프 감소에 v_texttoadd 변수와 행의 수를 건너 뛸 수 있습니다 :

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. 

는 또한 작업을 수행하기 위해 직선 SQL을 사용할 수 있습니다. 는 SQL 모델 절 예, 당신은 버전 10g 이상에있는 경우 :

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. 

감사합니다, 롭.

+0

+1 FOR ... IN ... LOOP 제안 및 예제. 커서 FOR 루프는 친구입니다 ;-) 추가 보너스 : 종종 FOR 루프에 커서 선택문을 삽입 할 수 있습니다. FOR REC IN (SELECT ...) LOOP – DCookie

0

필자는 항상 완벽하게 작동하는 Microsoft SQL에서 많은 커서 기반 솔루션을 만들었습니다. (좋은 옛날이었습니다! 내 SQL Server를 너무 많이 원했습니다!) 그러나이 질문에 대한 모든 대답은 나에게 잘못되었습니다. 커서의 마지막 행은 내가 제안한 방법을 얼마나 자세히 따르더라도 항상 두 번 실행됩니다.

도중 loop을 잊어 버리고 exit을 잊어 버리십시오. 이것은 이중 실행을 피하기 위해해야합니다 (거의 T-SQL에서 무엇을합니까!).모든 오라클 기술 자료 문서 및 포럼 게시물 (및 유래가) 분명히 잘못이 종료 된-A 루프 솔루션을 촉진 왜 난 정말 이해가 안

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; 

입니다!