SQL PL/SQL 프로시저 2_ 프로시저의 제어문과 반복문

2024. 9. 20. 16:28SQL

PL/SQL에서 사용할 수 있는 제어문과 반복문 종류

  • 단일 if문
  • if~else문
  • 다중 if문
  • case when
  • 무한 loop
  • whlie
  • for
  • exit
  • continue

오라클의 pl/sql에서는 블록안에서 사용할 수있는 제어문과 반복문이 존재한다. 파이썬이나 c언어와는 다르게 오라클에서는 위와같은 제어문 및 반복문을 단독으로 사용할 수  없고 pl/sql의 블록안에서만 사용이 가능하다.

 

 

단일 if문

--단일if문--
declare
v_number number :=1;
begin
  if v_number =1 then
     dbms_output.put_line('v_number는 1입니다.');
  end if;
  dbms_output.put_line('종료');
end;
/

declare
v_number number :=10;
begin
  if v_number > 100 then --거짓--
    dbms_output.put_line('v_number는 100보다 큽니다'); 
  end if;
  dbms_output.put_line('종료');
end;
/

단일 if문의 형식은 if 조건식 then 참일경우 출력할 문장으로 구성되어있다. 단일 if문이 경우 조건식이 거짓일때 출력할 문장이 없으며 오로지 참일경우에만 출력할 문장만 존재한다. 먼저 변수안에 값을 저장하고 만약 변수안에 저장된 값이 조건에 일치한다면 그 밑에 적은 실행문을 출력한다.

이렇게 pl/sql의 블록 안에서 if문과 같은 다른 제어문을 사용했다면 순서대로 제어문의 end, 전체 블록의 end를 순서대로 적어주어 마무리해야한다. if문의 경우 end if;의형태로 블록안에서 if문이 끝났을때 적어준다.

첫번째 쿼리문의 경우 조건이 참이기때문에 참일때만 실행되는 단일if문인 실행문이 실행되는것이고

두번째 쿼리문의 경우 조건에 거짓이기때문에 if문에서는 아무것도 출력되지 않으며 if문의 밖에있는 문장인 종료문장만 출력되어끝나는걸 확인할 수 있다.

 

 

if ~ else문

--if~else문--
declare
v_number number :=1;
begin
 if v_number = 1 then
  dbms_output.put_line('v_number가 1입니다');
 else
  dbms_output.put_line('v_number가 1이 아닙니다');
 end if;
  dbms_output.put_line('종료');
end;
/

if~else문의 경우 조건이 참일때 실행하는 if 실행문과 조건이 거짓일때 실행하는 else문을 같이 사용할 수 있다. 어차피 조건이 참이 아니라면 무조건 거짓인 구조이기때문에 이 경우 else문에는 따로 조건식을 적지 않고 바로 출력될 출력문만 기재한다.

위의 쿼리문의 경우 decalre절에 선언된 변수의 값이 1이기때문에 거짓인else문이 출력되지 않고 if문과 if문 밖에있는 종료 문구가 출력된 결과이다.

 

 

다중if문

--다중if문--
declare
v_number number :=4;
begin
 if v_number =1 then
  dbms_output.put_line('v_number가 1입니다');
 elsif v_number =2 then
  dbms_output.put_line('v_number가 2입니다');
 elsif v_number =3 then
  dbms_output.put_line('v_number가 3입니다');
 else
 dbms_output.put_line('v_number에 해당하는 값이 없습니다');
 end if;
 dbms_output.put_line('종료');
end;
/

다중 if문은 조건에 대한 답이 여러개일 경우 출력할 수 있다. elsif는 조건식이 거짓일때가 아니라 변수에 저장된 값이 변동될때 그에 맞는 여러개의 참이되는 조건문을 출력한다. 변수가 1이라면 if문의 실행문이, 2라면 첫번째 elsif문의 실행문이 출력되는 형식이다. 만약 if문과 elsif문의 모든 조건에도 부합하는 값이 없다면 else문을 통해 그외의 실행문을 출력할 수 있다.

위의쿼리문의 경우 벼눗에 자장된 값이 4이기때문에 그 무엇에도 적합한 조건이 없기때문에 else가 출력된걸 볼 수 있다.

 

 

case 문

--case 문--
declare
v_num number :=1;
v_numword varchar2(30);
begin
v_numword :=
case v_num  --변수에 case문 출력문 할당--
    when 1 then '하나'
    when 2 then '둘'
    when 3 then '셋'
    when 4 then '넷'
    else '그외의 값'
end;
dbms_output.put_line(v_numword);
end;
/


--case문에서 바로 출력하기--
declare
v_jumsu number :=99;
begin
case round(v_jumsu/10)
    when 10 then dbms_output.put_line('A학점');
    when 9 then dbms_output.put_line('A학점');
    when 8 then dbms_output.put_line('B학점');
    when 7 then dbms_output.put_line('B학점');
    when 6 then dbms_output.put_line('C학점');
    when 5 then dbms_output.put_line('D학점');
    end case;
end;
/

declare
v_num number :=99;
begin
case round(v_num/10)
     when 9 then dbms_output.put_line('A학점');
     when 8 then dbms_output.put_line('A학점');
     when 7 then dbms_output.put_line('B학점');
     when 6 then dbms_output.put_line('C학점');
     else dbms_output.put_line('점수가 너무 낮습니다');
     end case;
end;
/

case문은 sql에서 일반적으로 사용하는 case문과 사용법이 거의 비슷하다. 단 pl/sql에서는 then절에서 치환되는 값이 각각의 조건에 맞는 실행문이 되는것이다.

첫번째 쿼리문은 case의 then절을 변수안에 할당하고 case문이 끝난 쿼리문 밖에서 변수에 저장된 then절을 변수의 형태로 출력하는 방식이다.

이경우 출력문을 하나하나 적어줄 필요가 없어 간편하게 사용이 가능하며, 끝날때는 end절로만 끝내도 된다.

두번째 쿼리문의 경우 case문의 then절 자체에 출력문을  적어 case문의 실행과 동시에 결과문이 출력되도록한 형태이다. 이렇게 적은경우 따로 변수에 할당해주지 않아도 되며, case문을 끝낼때는 end case;문으로 끝내야 한다. 

case문의 경우 할당된 값이외의 값이 출력될 경우에는 반드시 else문을 사용하여 그외의값도 출력이 될 수 있도록 해야한다.

 

 

loop문(무한루프)

--loop문 사용하기--

--loop문(무한루프)--
declare
v_num number := 1;
begin
 loop
  dbms_output.put_line(v_num);
  v_num := v_num + 1;
 if v_num >5 then
 exit;
 end if;
 end loop;
 dbms_output.put_line('종료');
end;
/

loop문은 반복문이다. loop만을 사용하는 경우는 무한 반복이 되며, 이 경우 반복문을 강제종료하기 위해 if문과 exit문이 함께 사용된다. loop문으로 선언된 변수를 반복시키는데 반복시키면서 변수에 +1을 하고있다.

만약 이렇게 계속 1씩 증가하는 변수의 값이 5보다 커진다는 조건에 참이 될경우 강제 종료문인 exit를 만나서 반복문이 종료되는 형식이다. 이경우에는 순서대로 if문의 종료, loop문의 종료, 최종 블록의 종료문까지 적어서 쿼리문을 마무리 시켜주어야한다.

 

 

while loop형식

--while loop형식--
declare
v_no number := 1;
begin
 while v_no <=7 loop
  dbms_output.put_line(v_no);
  v_no := v_no + 1;
 end loop;
 dbms_output.put_line('종료');
end;
/

while loop문은 조건이 참일 동안에만 반복을 진행하는 반복문이다. 조건식에 거짓이 될경우 자동으로 반복이 종료되기때문에 무한히 참이 되는 조건을 적지않는다면 if문이나 exit문을 적어 강제 종료시켜줄 필요가없다. 위의 쿼리문의 경우 변수에 1을 저장하고 마찬가지로 반복문이 1번 반복될때마다 변수에 저장된 값을 출력함과 동시에 변수에 +1을 재할당 하여 1씩 증가하도록 했다.

조건식이 변수가 7보다 작을때이기때문에 1씩 증가하다가 변수가 8이되면 조건식에 거짓이 되기때문에 반복문이 종료된다.

마찬가지로 end loop문으로 반복문이 끝났다는걸 적어주어야한다.

 

 

 

for 반복문

--for 반복문--
begin
for i in 1..5 loop
 dbms_output.put_line(i);
 end loop;
end;
/

begin
for i in reverse 1..5 loop --숫자 거꾸로 출력--
 dbms_output.put_line(i);
end loop;
end;
/

--continue문과 for문 사용--
begin
for i in 1..10 loop
if i = 7 then
continue;
else
dbms_output.put_line(i);
end if;
end loop;
end;
/

for문은 반복가능한 객체를 적어주면 반복가능한 객체가 다 끝날때까지 반복해주는 반복문이다. 1~5를 출력하고싶다면

for 변수명 in 1..5의 형태로 적고 반대로 큰수에서 작은수로 출력하고싶다면 reverse 1..5의 형태로 적어 출력해준다. 마찬가지로 반복가능한 객체가 전부 끝나면 자동적으로 반복이 끝나기때문에 강제 종료시켜줄 필요가없고 end loop문으로 반복문을 마무리해준다.

두번째 쿼리문의 경우 contiue와 함께 쓰였는데 continue는 해당 값을 건너뛰는데 반복문이 종료되지않고 계속되는 명령어이다. for문의 반복가능 객체에서 숫자가 반복되다가 if문의 조건식인 7과 같아진다면 참이되기때문에 continue를 만나 출력이 되지 않는것이다.

 

for문으로 continue 활용하기

--continue문으로 짝수만 출력하기--
begin
for i in 1..10 loop
 if mod(i,2)=0 then
 dbms_output.put_line(i);
 else
 continue;
 end if;
 end loop;
end;
/

--같은방법으로 홀수만 출력하기--
begin
for i in 1..10 loop
if mod(i,2) = 1 then
dbms_output.put_line(i);
else
continue;
end if;
end loop;
dbms_output.put_line('홀수 출력 종료');
end;
/

continue를 활용하면 반복가능 객체에서 내가 원하는 값만 출력해낼 수 있다. for문에서 숫자가 반복이 되도록 해준다음에 if문에서 적절한 조건식을 준 다음에 그 조건식이 참이되면 출력이 되고, 그렇지 않다면 else문의 출력값에 continue를 적어, 내가 원하지 않는 값은 아예 출력이 되지 않도록 하는것이다. 위의 쿼리문의 경우는 나머지를 계산해주는 mod 함수를 이용하여 짝수 홀수만 각각 출력하는 쿼리문이다.

 


학습일기

오늘은 프로시저에서도 제어문과 반복문 파트를 복습했는데, 사실 맨 처음 프로시저를 접했을때는 아예 다른 언어를 한번도 접해보지 않았을때라 제어문과 반복문모두 프로시저를 공부하면서 완전 처음봤다. 그거때문인지 지금 파이썬과 r을 공부하면서 제어문과 반복문에 조금이나마 익숙해서인지 처음 배운 당시보다는 훨씬 수월하게 복습했다. 그래도 프로시저로 적으려면 약간은 어려운건 사실이지만..!! 쿼리문을 쓰면서 자주 오류가 발생하진 않았는데 주로 제어문과 반복문의 end에 세미콜론을 찍지않아서 발생한 오타 오류가많아서 이부분만 신경쓰면 될것같다..!!