✅ 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; /
문제 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; /
문제 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_num
가 2일때v_count1
,v_count2
,v_count3
....v_count9
2.v_num
가 3일때v_count1
,v_count2
,v_count3
....v_count9
3.v_num
가 4일때v_count1
,v_count2
,v_count3
....v_count9
4.v_num
가 5일때v_count1
,v_count2
,v_count3
....v_count9
.
.
.
7.v_num
가 8일때v_count1
,v_count2
,v_count3
....v_count9
8.v_num
가 9일때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문 조건이 맞아야 안에 실행문이 반복되어 실행된다.
문제 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_count
를 1로 초기화하자!!!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_line
과v_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;
/
도구 > 환경설정 > 디버거 > DBMS_DEBUG 사용체크
sqldeveloper에서 프로시저 pro77을 클릭하면 소스코드가 보이는데, 여기서 중단점을 찍어야한다. (중단점을 찍는 이유는, 중단점에서 일시 멈춤을 하기 위해)
pro77 오른쪽 마우스를 눌러서 디버그를 위한 컴파일을 한다.
무당벌레 아이콘 누르기!
오른쪽 아래 탭에 스마트 데이터 탭을 클릭하고
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; /
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의 배수가 아니면 아무것도 하지마라! 라는 뜻.
✏️ PL/SQL 변수의 종류 3가지
1. 스칼라 변수
: 단일값만 저장
2. 조합 변수
: 여러개 값을 저장 (레코드, 컬렉션)
3. 바인드 변수
: DECLARE, END 외부에서 선언한 텀블러같은 호스트 변수
✏️ 배우게 될 것들!
PL/SQL 컬렉션 및 레코드
설명유저 정의 PL/SQL 레코드
생성%ROWTYPE
속성을 사용하여 PL/SQL 레코드 생성연관 배열
생성
- INDEX BY 테이블
- INDEX BY 레코드 테이블
✏️ 스칼라 유형과는 달리 여러개 값을 저장하는 변수
✔️ 두 가지 유형이 있습니다.
✅ 레코드는 suit case라고 생각하자.
✔️ 스칼라, RECORD 또는 INDEX BY 테이블 데이터 유형의 구성
요소(필드라고 함)를 하나 이상 포함해야 합니다. (하나면 스칼라)
✔️ C와 C++를 포함한 대부분의 3세대 언어 구조와 유사합니다. (파이썬의 리스트 유형)
✔️ 사용자 정의 데이터 유형이며 테이블 행의 부분 집합일
수 있습니다. (emp테이블 smith의 데이터들로만)
✔️ 필드 컬렉션을 논리적 단위로 처리합니다.
✔️ 테이블에서 데이터 행을 패치(fetch)하여 처리하는
데 편리합니다 (emp테이블에서 데이터 가져올 때 누구꺼에 대한 데이터 fetch...한번에 한행 가져오기 편하다.
)
예제. 사원번호를 물어보게하고 사원번호를 입력하면 해당 사원의 사원이름, 월급, 직업이 출력되는 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를 이용해서 레코드 변수를 선언하면 다음의 기능들을 이용할 수 있다.
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;
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; /