복습

✅ loop문의 종류
1. basic loop
2. while loop
3. for loop

문제 67. (basic loop 복습) 구구단 2단을 basic loop로 수행하시오

set serveroutput on
declare
   v_count  number(10) := 0;
begin 
   loop
       v_count := v_count + 1;
       dbms_output.put_line('2 x '|| v_count || ' = ' || 2*v_count);
       exit when v_count = 9;
   end loop;
end;
/


오늘의 TIL

  1. basic loop 복습
  2. while loop 복습
  3. for loop 복습
  4. loop문으로 구구단 출력
  5. 이중 loop문
  6. PL/SQL CONTINUE 문
  7. 조합 변수
  8. PL/SQL 레코드와 컬렉션의 차이
  9. %ROWTYPE

문제 68. (basic loop 복습) 위 코드를 수정해서, 단을 물어보게하고 단을 입력하면 해당 구구단의 단이 출력되게 하시오

set serveroutput on
accept  p_num  prompt '단을 입력하세요'
declare
   v_count  number(10) := 0;
   v_num    number := &p_num;
begin 
   loop
       v_count := v_count + 1;
       dbms_output.put_line(v_num||' x '|| v_count || ' = ' || v_num*v_count);
       exit when v_count = 9;
   end loop;
end;
/

문제 69. (while loop 복습) 구구단 2단을 while loop문으로 구현하기

set serveroutput on
declare
   v_count  number(10) := 0;
begin 
   while v_count < 9 loop
       v_count := v_count + 1;
       dbms_output.put_line('2 x '|| v_count || ' = ' || 2*v_count);
   end loop;
end;
/

while loop에서는 declare절에 0을 할당해주는것이 굉장히 중요하다. null이 들어가면 조건자체가 안맞아서 안나온다.

완료되었다고 나오지만, 데이터는 나오지않음

문제 70.(while loop 복습) 구구단의 단을 물어보고 단을 입력하면 해당 단의 구구단이 출력되게 하시오

set serveroutput on
accept  p_num  prompt '단을 입력하세요'
declare
   v_count  number(10) := 0;
   v_num    number := &p_num;
begin 
   while v_count < 9 loop
       v_count := v_count + 1;
       dbms_output.put_line(v_num||' x '|| v_count || ' = ' || v_num*v_count);
   end loop;
end;
/

문제 71. (for loop 복습) 구구단 2단을 for loop로 출력해보기

begin
    for v_count in 1..9 loop
      dbms_output.put_line('2 x '|| v_count || ' = ' || 2*v_count);
    end loop;
end;
/

(for loop 복습) 구구단의 단을 물어보고 단을 입력하면 해당 단의 구구단이 출력되게 하시오

accept  p_num  prompt '단을 입력하세요'
declare
   v_num    number := &p_num;
begin 
    for v_count in 1..9 loop
      dbms_output.put_line(v_num||' x '|| v_count || ' = ' || v_num*v_count);
    end loop;
end;
/

문제 72. for loop문으로 구구단 2, 3단을 출력

내가 한 답

begin
    for v_count in 1..9 loop
      dbms_output.put_line('2 x '|| v_count || ' = ' || 2*v_count || '   ' || '3 x '|| v_count || ' = ' || 3*v_count );
    end loop;
end;
/


수업에서 한 답

begin
    for v_count in 1..9 loop
      dbms_output.put_line('2 x '|| v_count || ' = ' || 2*v_count);
    end loop;
      dbms_output.put_line('   ');
    for v_count in 1..9 loop
      dbms_output.put_line('3 x '|| v_count || ' = ' || 3*v_count);
    end loop;
end;
/

이중 for loop문

문제 73. (이중loop)그렇다면 9단까지 모두 뽑아보자

prompt 구구단 전체를 출력합니다. //그냥 메세지 쓰고싶어서 작성
begin
  for v_num in 2..9 loop // 단을 출력하는 반복문
    for v_count in 1..9 loop
      dbms_output.put_line(v_num||' x '|| v_count || ' = ' || v_num*v_count);
    end loop;
    dbms_output.put_line('   ');
  end loop;  
end;
/  


✅ v_num가 2 ~ 9까지 8번 실행문을 반복한다.
1. v_num2일때 v_count1, v_count2, v_count3....v_count9
2. v_num3일때 v_count1, v_count2, v_count3....v_count9
3. v_num4일때 v_count1, v_count2, v_count3....v_count9
4. v_num5일때 v_count1, v_count2, v_count3....v_count9
.
.
.
7.v_num8일때 v_count1, v_count2, v_count3....v_count9
8.v_num9일때 v_count1, v_count2, v_count3....v_count9
💡 v_num은 실행문을(v_count) 8번 실행하는데 실행문 안에서의 반복문은 9번이 일어난다.

문제 74. 위 출력되는 결과에서 짝수단만 출력하기

begin
  for v_num in 2..9 loop
     if mod(v_num,2) = 0 then     
        for v_count in 1..9 loop
          dbms_output.put_line(v_num||' x '|| v_count || ' = ' || v_num*v_count);
        end loop;        
     dbms_output.put_line('   ');
     end if;
  end loop;  
end;
/  

✅ if문 조건이 맞아야 안에 실행문이 반복되어 실행된다.

시험문제 !(while loop 에서 초기화)

문제 75. (책에없는) 이중 while loop !

set serveroutput on
declare
   v_count  number(10) := 0;
   v_dan    number := 2;
begin 
   while v_dan <= 9 loop
       while v_count < 9 loop
           v_count := v_count + 1; -- 곱하는 수를 증가시키는 코드(2단의 x1, x2, x3..)
           dbms_output.put_line(v_dan||' x '|| v_count || ' = ' || v_dan*v_count);
       end loop;
    v_dan := v_dan + 1; --단을 증가시키는 코드   
    // 여기에 뭐가 있어야한다.
    end loop;
end;
/

이렇게만 뽑으면 2단밖에 안나온다. 왜냐면 2단일 때 v_count가 이미 9까지 되었기때문! 그래서 다시돌 때 9 < 9 라는 조건때문에 이후 단들이 나오지 않는다. 그렇다면 v_count1로 초기화하자!!!

set serveroutput on
declare
   v_count  number(10) := 0;
   v_dan    number := 2;
begin 
   while v_dan <= 9 loop
       while v_count < 9 loop
           v_count := v_count + 1; -- 곱하는 수를 증가시키는 코드(2단의 x1, x2, x3..)
           dbms_output.put_line(v_dan||' x '|| v_count || ' = ' || v_dan*v_count);
       end loop;
    v_dan := v_dan + 1; --단을 증가시키는 코드   
    v_count := 0; // ★시험문제 !!! 단이 증가될 때 마다 다시 0로 초기화해야한다.
    end loop;
end;
/

위 코드 수정함!!

declare
   v_count  number(10) := 1;
   v_dan    number := 2;
begin 
   while v_dan <= 9 loop
       while v_count <= 9 loop
           dbms_output.put_line(v_dan||' x '|| v_count || ' = ' || v_dan*v_count);
           v_count := v_count + 1; -- 곱하는 수를 증가시키는 코드(2단의 x1, x2, x3..)
       end loop;
    v_dan := v_dan + 1; --단을 증가시키는 코드   
    v_count := 1;
    end loop;
end;
/

문제 76. 위 결과에서 홀수단만 출력

set serveroutput on
declare
   v_count  number(10) := 1;
   v_dan    number := 2;
begin 
   while v_dan <= 9 loop
     if mod(v_dan,2) = 1 then     
       while v_count <= 9 loop
           dbms_output.put_line(v_dan||' x '|| v_count || ' = ' || v_dan*v_count);
           v_count := v_count + 1; -- 곱하는 수를 증가시키는 코드(2단의 x1, x2, x3..)
       end loop;
    end if;   
    v_dan := v_dan + 1; --단을 증가시키는 코드   
    v_count := 1; // 초기화 하는 코드 !!!
    dbms_output.put_line('   ');
    end loop;
end;
/

✅ 문제 75, 76 차이점은 실행문 조건에 v_count < 9 loop를 v_count <= 9 loop로 변경해주었고 dbms_output.put_linev_count := v_count + 1;의 순서를 바꾸었다.
✅ 초기화 하는 코드도 0에서 1로 바꿨다.

문제 77. 위 코드를 디버깅해서 코드상에서 데이터의 흐름을 확인하시오

create or replace procedure pro77
is
   v_count  number(10) := 1;
   v_dan    number := 2;
begin 
   while v_dan <= 9 loop
     if mod(v_dan,2) = 1 then     
       while v_count <= 9 loop
           dbms_output.put_line(v_dan||' x '|| v_count || ' = ' || v_dan*v_count);
           v_count := v_count + 1;
       end loop;
    end if;   
    v_dan := v_dan + 1; 
    v_count := 1; 
    dbms_output.put_line('   ');
    end loop;
end;
/

코드 디버깅 환경설정 방법

  1. 도구 > 환경설정 > 디버거 > DBMS_DEBUG 사용체크

  2. sqldeveloper에서 프로시저 pro77을 클릭하면 소스코드가 보이는데, 여기서 중단점을 찍어야한다. (중단점을 찍는 이유는, 중단점에서 일시 멈춤을 하기 위해)

  3. pro77 오른쪽 마우스를 눌러서 디버그를 위한 컴파일을 한다.

  4. 무당벌레 아이콘 누르기!

  5. 오른쪽 아래 탭에 스마트 데이터 탭을 클릭하고

  6. F7을 누르면서 디버깅을 진행한다.

문제 78. 구구단 2단을 출력하는 기본 basic loop문 출력하기

set serveroutput on
declare
   v_count  number(10) := 0;
begin 
   loop
       v_count := v_count + 1;
       dbms_output.put_line('2 x '|| v_count || ' = ' || 2*v_count);
       exit when v_count = 9;
   end loop;
end;
/

문제 79. 전체 구구단을 출력하는 코드를 이중 basic loop문으로 작성

set serveroutput on
declare
   v_count  number(10) := 1;
   v_dan    number := 2;
begin 
   loop
       loop
           dbms_output.put_line(v_dan||' x '|| v_count || ' = ' || v_dan*v_count);
           v_count := v_count + 1;
           exit when v_count > 9;
       end loop;

    v_dan := v_dan + 1;   -- 단을 증가시키는 코드
    v_count := 1;         -- v_count를 다시 1로 변경하는 코드
    exit when v_dan > 9;  -- 밖의 루프문을 종료시키는 코드 
   end loop;    
end;
/

루프문 권장 사용법

✅ 루프 안의 명령문이 적어도 한 번 실행되어야 하는 경우에는
basic 루프를 사용합니다.
✅ 매번 반복을 시작할 때마다 조건이 평가되어야 하는 경우에는
while 루프를 사용합니다.
✅ 반복 횟수를 알 수 있는 경우에는 for 루프를 사용합니다.

문제 80. 책 페이지번호 171번의 (위 이미지) 레이블을 사용한 루프문 코드를 참고해서 문제 79번의 basic loop문 코드에 레이블을 추가해서 코딩하기

declare
   v_count  number(10) := 1;
   v_dan    number := 2;
begin 
   loop
       loop
           dbms_output.put_line(v_dan||' x '|| v_count || ' = ' || v_dan*v_count);
           v_count := v_count + 1;
           exit when v_count > 9;
       end loop;

    v_dan := v_dan + 1;   -- 단을 증가시키는 코드
    v_count := 1;         -- v_count를 다시 1로 변경하는 코드
    exit when v_dan > 9;  -- 밖의 루프문을 종료시키는 코드 
   end loop;    
end;
/

정답 코드

declare   
       v_dan      number(10) := 2; 
       v_count   number(10) := 1 ;

begin
  <<Outer_loop>>
    loop 
       <<Inner_loop>>
          loop
                dbms_output.put_line( v_dan ||'  x  ' || v_count || ' = ' || v_dan * v_count );
                v_count  :=  v_count +  1 ;
                exit  Inner_loop when  v_count > 9;
         end  loop  Inner_loop;

        v_dan := v_dan + 1;  -- 단을 증가 시키는 코드 
        v_count := 1;            --  v_count 를 다시 1로 변경하는 코드
        exit Outer_loop when  v_dan > 9;   -- 밖의 루프문을 종료시키는 코드
   end loop Outer_loop;

end;
/

문제 81. 위 이중 basic loop 문에 코드를 추가해서 구구단 짝수단만 출력되게 하시오

레이블 없는 것

declare
   v_count  number(10) := 1;
   v_dan    number := 2;
begin 
   loop
    if mod(v_dan,2) = 0 then     
       loop
           dbms_output.put_line(v_dan||' x '|| v_count || ' = ' || v_dan*v_count);
           v_count := v_count + 1;
           exit when v_count > 9;
       end loop;
       dbms_output.put_line('   ');
    end if;   

    v_dan := v_dan + 1;   -- 단을 증가시키는 코드
    v_count := 1;         -- v_count를 다시 1로 변경하는 코드
    exit when v_dan > 9;  -- 밖의 루프문을 종료시키는 코드 
   end loop;    
end;
/

레이블 있는 것

declare   
       v_dan      number(10) := 2; 
       v_count    number(10) := 1 ;

begin
  <<Outer_loop>>
    loop 
     if mod(v_dan,2) = 0 then    
       <<Inner_loop>>
          loop
                dbms_output.put_line( v_dan ||'  x  ' || v_count || ' = ' || v_dan * v_count );
                v_count  :=  v_count +  1 ;
                exit  Inner_loop when  v_count > 9;
         end  loop  Inner_loop;
         dbms_output.put_line('   ');
      end if;   

        v_dan := v_dan + 1;  -- 단을 증가 시키는 코드 
        v_count := 1;            --  v_count 를 다시 1로 변경하는 코드
        exit Outer_loop when  v_dan > 9;   -- 밖의 루프문을 종료시키는 코드
   end loop Outer_loop;

end;
/

PL/SQL CONTINUE 문

CONTINUE문은, loop문의 옵션입니다!
루프문으로 특정 실행문을 반복할 때 어느 조건에 해당하는 부분을 실행하지 않게 할 때 유용합니다.
✔️ 다 반복하지 말고, 이 부분은 그냥 실행하지 말고 다른거 해라!! (성능 좋아질 수 있음)
✔️ 지금하는거는 무시하고 다른걸 계속해라.

문제 82. for loop문을 이용해서, 숫자 1번부터 10번까지 출력하기

begin
    for v_count in 1..10 loop
      dbms_output.put_line(v_count);
    end loop;
end;
/  

문제 83. 위에서 출력되는 결과중에 숫자 4는 출력되지 않게 하시오

begin
    for v_count in 1..10 loop
      if v_count !=4 then
         dbms_output.put_line(v_count);
      end if;  
    end loop;
end;
/  
begin
    for v_count in 1..10 loop
      if v_count =4 then
         continue; // 4가 나오면 여기가 실행되서 4가 무시됨
      end if;  

      dbms_output.put_line(v_count); // 4 이외는 여기 실행
    end loop;
end;
/  


문제 85. 1부터 10까지의 숫자중에 짝수만 출력(continue사용)

begin
    for v_count in 1..10 loop
      if mod(v_count,2)=1 then // v_count가 홀수면 무시해라!!
         continue;             // 다른거 하던거 계속해라!
      end if;  

      dbms_output.put_line(v_count); // 요기실행
    end loop;
end;
/  

문제 86. 1부터 50까지의 숫자중에서 7의 배수만 출력하시오

begin
    for v_count in 1..50 loop
      if mod(v_count,7)!= 0 then
         continue; 
      end if;  

      dbms_output.put_line(v_count);
    end loop;
end;
/ 

if mod(v_count,7)!= 0 then 는 , v_count를 7로 나누었을 때 나머지값이 0이 아닌 것들. 즉, 7의 배수가 아닌것들 이고

 if mod(v_count,7)!= 0 then
         continue; 
      end if;  

위 코드는 7의 배수가 아니면 아무것도 하지마라! 라는 뜻.

📖6장 조합 변수

✏️ PL/SQL 변수의 종류 3가지
1. 스칼라 변수 : 단일값만 저장
2. 조합 변수 : 여러개 값을 저장 (레코드, 컬렉션)
3. 바인드 변수 : DECLARE, END 외부에서 선언한 텀블러같은 호스트 변수

✏️ 배우게 될 것들!

  • PL/SQL 컬렉션 및 레코드 설명
  • 유저 정의 PL/SQL 레코드 생성
  • %ROWTYPE 속성을 사용하여 PL/SQL 레코드 생성
  • 연관 배열 생성
    • INDEX BY 테이블
    • INDEX BY 레코드 테이블

조합 데이터 유형의 종류

✏️ 스칼라 유형과는 달리 여러개 값을 저장하는 변수
✔️ 두 가지 유형이 있습니다.

  • PL/SQL 레코드
  • PL/SQL 컬렉션
    • 연관 배열(INDEX BY 테이블)
    • 중첩 테이블
    • VARRAY

PL/SQL 레코드와 컬렉션의 차이


✅ 레코드는 suit case라고 생각하자.

PL/SQL 레코드

✔️ 스칼라, RECORD 또는 INDEX BY 테이블 데이터 유형의 구성
요소(필드라고 함)를 하나 이상 포함해야 합니다. (하나면 스칼라)
✔️ C와 C++를 포함한 대부분의 3세대 언어 구조와 유사합니다. (파이썬의 리스트 유형)
✔️ 사용자 정의 데이터 유형이며 테이블 행의 부분 집합일
수 있습니다. (emp테이블 smith의 데이터들로만)

✔️ 필드 컬렉션을 논리적 단위로 처리합니다.
✔️ 테이블에서 데이터 행을 패치(fetch)하여 처리하는
데 편리합니다
(emp테이블에서 데이터 가져올 때 누구꺼에 대한 데이터 fetch...한번에 한행 가져오기 편하다.
)

PL/SQL 레코드 생성


레코드 생성 예제

예제. 사원번호를 물어보게하고 사원번호를 입력하면 해당 사원의 사원이름, 월급, 직업이 출력되는 pl/sql 코드 작성하기

accept p_empno prompt '사원번호를 입력하세요!'

declare 
  v_empno   emp.empno%type := &p_empno;
  
  type   t_rec  is record
  (v_ename  emp.ename%type,
   v_sal    emp.sal%type,
   v_job    emp.job%type ); --레코드 변수 선언
   
v_myrec  t_rec; --레코드 변수 생성

begin 
   select ename, sal, job into v_myrec
     from emp
     where empno = v_empno;

     -- v_myrec.v_sal := 9000;
     
     -- 이부분에 위 코드 쓰면, 월급은 무조건 9000으로 설정되어 출력된다.
     -- 이 코드가 없다면 원래 테이블에 있는 sal데이터가 나옴!
dbms_output.put_line(v_myrec.v_ename || ' ' || 
                     to_char(v_myrec.v_sal) || ' ' || v_myrec.v_job);
end;
/

문제 87. 사원테이블에서 이름을 물어보게하고, 이름을 입력하면 해당 사원의 직업, 월급, 입사일이 출력되게 하는데 입사일은 오늘날짜로 출력되게 하시오!

accept p_ename prompt '이름을 입력하세요!'

declare 
  v_ename   emp.ename%type := upper('&p_ename');

  type   t_rec  is record
  (v_hiredate  emp.hiredate%type,
   v_sal    emp.sal%type,
   v_job    emp.job%type ); --레코드 변수 선언

v_myrec  t_rec; --레코드 변수 생성

begin 
   select hiredate, sal, job into v_myrec
     from emp
     where ename = v_ename;

    v_myrec.v_hiredate := SYSDATE;

dbms_output.put_line('직업은 ' || v_myrec.v_job);
dbms_output.put_line('월급은 ' || v_myrec.v_sal);
dbms_output.put_line('입사일은 ' || v_myrec.v_hiredate);
                   
end;
/

%ROWTYPE의 이점

%ROWTYPE를 이용해서 레코드 변수를 선언하면 다음의 기능들을 이용할 수 있다.
1. slect 한번에

SELECT * INTO 레코드 변수명 from emp where empno = v_empno
-> *가 레코드 변수명에 다 들어간다.

2. 업데이트 한번에

update emp
  set row = 레코드 변수명
  where empno = v_empno;

3. insert할 때 values 한번에

insert inro emp values 레코드 변수명

예제.
1. emp테이블과 똑같은 emp_test 테이블을 데이터는 가져오지 말고, 구조만 구성한다.

create table emp_test
as
  select * 
    from emp
    where 1=2;
  1. 사원번호를 물어보게하고, 사원번호를 입력하면 해당 사원의 모든 데이터가 emp_test 테이블에 입력되는 PL/SQL코드를 작성하기(레코드 변수 사용)
accept p_empno prompt '사원번호를 입력하세요!'

declare 
  v_empno   emp.empno%type := &p_empno;
  v_emp     emp%rowtype; -- emp테이블의 모든 데이터를 담을 수 있는 데이터타입을 담은게 만들어짐
begin 
   select * into v_emp
      from emp
      where empno  = v_empno;
 
    v_emp.sal := 0; --sal은 다 0으로 표시되도록
    insert into emp_test values v_emp;                  
end;
/


✅ 잘 들어갔다!

문제 88. (오늘의 마지막 문제) 위 코드를 수정하여 개인정보가 emp_test에 입력되지 않도록 월급뿐만아니라 데이터도 아래와 같이 변경되어 입력되게 하세요!
월급은 0
입사일은 오늘날짜
부서번호 0
커미션은 null

accept p_empno prompt '사원번호를 입력하세요!'

declare 
  v_empno   emp.empno%type := &p_empno;
  v_emp     emp%rowtype; -- emp테이블의 모든 데이터를 담을 수 있는 데이터타입을 담은게 만들어짐
begin 
   select * into v_emp
      from emp
      where empno  = v_empno;
  
    v_emp.sal := 0; 
    v_emp.hiredate := SYSDATE;
    v_emp.deptno := 0;
    v_emp.comm := null;

    insert into emp_test values v_emp;                  
end;
/

profile
Slow and steady wins the race.

0개의 댓글