[pl/sql]loof 질문 0 10 1,179

by 오라클초보자 [PL/SQL] loof procedure pl/sql cursor [2020.02.28 10:04:37]


test라는 테이블이 소유 컬럼은 소유이고 금전 컬럼은 null값일때

test테이블의의 pk값을 1건씩 읽어서

test2라는 테이블을 검색하는데

이때 test2의 col1컬럼이 한건이면 col5데이터를 읽고 1건이상이면 col2 컬럼이 정답인 col5 데이터만 읽으라는 과제를 받이서 작성해본 쿼리인데

create or replace procedure p_test
is
cursor c_1 is select * from test where col3= '소유' and col4 is null; 
r_1 c_1 %ROWTYPE;
l_cnt test2%ROWTYPE;
begin
open c_1;
loop
fetch c_1 into r_1;
exit when c_1%notfound;
select count(*) into l_cnt  from test2 where col1= r_1.col1;
if l_cnt = 1 then
DBMS_OUTPUT.put_line(test2 .col5);
else 
select 주소 from test2 where col2 = '정답';
end if;
end loop;
close c_1;
end p_test;

프로시저 SCOTT.p_test@scott

오류(11,1): PL/SQL: SQL Statement ignored

오류(11,29): PL/SQL: ORA-00913: 값의 수가 너무 많습니다

오류(12,1): PL/SQL: Statement ignored

오류(12,10): PLS-00306: '=' 호출 시 인수의 갯수나 유형이 잘못되었습니다

이런오류가 뜹니다.

수정하면 다른문제가 생기고 계속 반복만하다가 선배님들에게 어디가 잘못됬는지 조언을 구해봅니다ㅠㅠ

by 마농 [2020.02.28 10:26:40]

1. 변수 타입 오류
 - l_cnt 는 %rowtype 이 아닌 number 로 선언하시면 되구요.
2. 카운트 1 일 때의 처리
 - 바로 출력 못하죠.
 - 우선 Select 해오는 부분이 있어야죠.
3. select 구문 오류
 - select 구문은 단독으로 못 씁니다. into 절이 필요합니다.
 - into 절을 쓰려면 값을 받을 변수도 하나 더 필요하겠네요.
4. 생각해 볼 문제.
 - 1건 이상인 경우 그중 정답인 건은 1건 뿐인가요?
 - 정답이 1건 이상인 경우가 없어야 합니다.


by 오라클초보자 [2020.02.28 11:27:53]
create or replace procedure p_test

is

cursor c_1 is select * from test where col3= '소유' and col4 is null;

r_1 c_1 %ROWTYPE;

r_2 VARCHAR(1000);
l_cnt VARCHAR(1000);
l_cnt_2 VARCHAR(1000);

begin

open c_1;

loop

fetch c_1 into r_1;

exit when c_1%notfound;

select col5 into r_2 from test_2;

select col1 into l_cnt  from test2 where col1 in(select col1 from test2 where group by col1 having count(*) =1);

select col1 into l_cnt_2  from test2 where col1 in(select col1 from test2 where group by col1 having count(*) >1) and col2='정답';

if l_cnt = r_1.col1 then

DBMS_OUTPUT.put_line(r_2);

end if

if if l_cnt_2 = r_1.col1 then

DBMS_OUTPUT.put_line(r_2);

end if;

end loop;

close c_1;

end p_test;

정답인 건은 1건뿐이고 선배님 말씀대로 변수타입 수정, into절 및 변수추가 해보니 문제가 해결되었습니다 감사합니다.


by 마농 [2020.02.28 13:02:36]

글쎄요? 해결하셨다니 다행이긴 하지만...
위 코드는 문법도 많이 틀리고 의미상으로도 많이 틀린 듯 하네요.
into 절을 쓰면 1건만 조회되어야 합니다.
위 쿼리는 조건이 없어 여러건이 조회되겠네요.


by 마농 [2020.02.28 13:39:29]
CREATE OR REPLACE PROCEDURE p_test
IS
  CURSOR c_1 IS
  SELECT *
    FROM test
   WHERE col3 = '소유'
     AND col4 IS NULL
  ;
  r_1   c_1%ROWTYPE;
  r_2   VARCHAR2(100);
  l_cnt NUMBER(3);
BEGIN
  OPEN c_1;
  LOOP
    FETCH c_1 into r_1;
    EXIT WHEN c_1%NOTFOUND;
    SELECT COUNT(*)
      INTO l_cnt
      FROM test2
     WHERE col1 = r_1.col1
    ;
    r_2 := '';
    IF l_cnt = 1 THEN
      SELECT col5
        INTO r_2
        FROM test2
       WHERE col1 = r_1.col1
      ;
    ELSIF l_cnt > 1 THEN
      SELECT col5
        INTO r_2
        FROM test2
       WHERE col1 = r_1.col1
         AND col2 = '정답'
      ;
    END IF;
    DBMS_OUTPUT.put_line(r_1.col1 || ' : ' || r_2);
  END LOOP;
  CLOSE c_1;
END;
/

 


by 오라클초보자 [2020.03.02 11:49:44]

제가 쓴 코드로는 컴파일은 됬으나 말씀하신대로 into절에 결과값이 2건이상 나와 실행시 오류가 발생했습니다.

아래 써주신 로직대로 수행해보니 elsif l_cnt >= then
        SELECT 대지_면적
        INTO r_land
        FROM EXT_LAYOUT_t
       WHERE 대지_위치_1 = r_1.대지_위치; and 신_구_대장_구분_코드_명 = '신대장';에서  SELECT 부분에서 오류가 발생했습니다...

추가로 혹시 r_2 := '';이부분을 추가한 이유가 r_2의 값을 문자로 표기하기 위해서인지 여쭤봐도 될까요?


by 마농 [2020.03.02 12:50:13]

1. 어떤 오류가 나나요? 구체적으로 명시해 주세요.
 - 동일한 오류가 난다면? 분석이 잘못 된 듯 하네요. 1건이 아닌 듯.
 - 정답 건이 여러건이면 어떤걸 가져와야 하는지 기준이 필요하겠네요.
 - 아무거나 가져와도 된다면? MIN/MAX 나 ROWNUM 사용하시면 됩니다.
2. 변수 초기화
 - 반복 구문 안에서 기존 변수 값을 초기화 하는 것입니다.


by 오라클초보자 [2020.03.02 13:21:53]

제가 오타를 냈었네요...

CREATE OR REPLACE PROCEDURE p_test
IS
  CURSOR c_1 IS
  SELECT *
    FROM test
   WHERE col3 = '소유'
     AND col4 IS NULL
  ;
  r_1   c_1%ROWTYPE;
  r_2   VARCHAR2(100);
  l_cnt NUMBER(3);
BEGIN
  OPEN c_1;
  LOOP
    FETCH c_1 into r_1;
    EXIT WHEN c_1%NOTFOUND;
    SELECT COUNT(*)
      INTO l_cnt
      FROM test2
     WHERE col1 = r_1.col1
    ;
    r_2 := '';
    IF l_cnt = 1 THEN
      SELECT col5
        INTO r_2
        FROM test2
       WHERE col1 = r_1.col1
      ;
    ELSIF l_cnt > 1 THEN
      SELECT col5
        INTO r_2
        FROM test2
       WHERE col1 = r_1.col1
         AND col2 = '정답'
      ;
   
    END IF;
DBMS_OUTPUT.put_line(r_1.col1 || ' : ' || r_2);

  END LOOP;
  CLOSE c_1;
END;
/
위와같이 실행시 정상동작했습니다. 감사합니다!

 


by 오라클초보자 [2020.03.02 16:06:41]

혹시 실례가 되지 않는다면 위의 코드로 출력한 col5값을 temp테이블에 insert하는법도 여쭤봐도 될까요?

어느 부분에 insert문을 삽입해야 정상동작되는지 모르겠습니다..

혼자 해볼려고 했는데 잘 안되네요ㅠㅠ

temp테이블에도 col5컬럼은 생성한 상태입니다.


by 마농 [2020.03.02 16:52:26]

dbms_output 찍고 있는 위치요.


by 오라클초보자 [2020.03.02 16:52:44]

감사합니다.좋은하루되세요^^

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입