오라클 8일차

8. PL-SQL개요및 작성법



– 기존의 SQL/Plus, SQL Developer
SQL+프로그램적 요소(변수의 자료형,제어문, 프로시저,함수사용)

SQL> declare
                 a number;
                 b number;
                 c number;
             begin
                 a:=12;
                 b:=11;
                 c:=a+b;
             end;
             /
PL/SQL 처리가 정상적으로 완료되었습니다.
<문제1> PL-SQL구문을 연습
SQL> set serveroutput on –> 출력하기 처음에 한번씀
SQL> ed
file afiedt.buf(이)가 기록되었습니다

  1  declare
  2                   a number;
  3                   b number;
  4                   c number;
  5           begin
  6                a:=12;
  7                b:=11;
  8                c:=a+b;
  9           — System.out.println(“<result c>” + c);
 10               dbms_output.put_line(‘<result c>’);
 11               dbms_output.put_line(c);
 12*          end;
SQL> /
<result c>
       23
PL/SQL 처리가 정상적으로 완료되었습니다.
 SQL Developer툴을 사용 —
C:\jdk1.8\bin\java.exe
실행화면
 sql developer

파일 타입 설정

filetype

접속:test
사용자이름:scott
비빌번호:tiger
호스트이름:localhost
포트:1521
SID:orcl로 설정
테스트버튼 클릭->성공

newdata-conn

글꼴설정

font
 =============================
<문제2> 산술연산자를 이용해서 출력
begin
    dbms_output.put_line(2*2);/* 4 */
    dbms_output.put_line(81/9);/* 9 */
    dbms_output.put_line(3+3);/* 6 */
    dbms_output.put_line(12-7);/* 5 */
    dbms_output.put_line(2**3);/* 8 */
end;
/
실행화면
4
9
6
5
8
============================
<문제3> select~into구문을 이용해서 불러오기
Ex) 부서명이 ACCOUNTING인 부서번호,위치?
declare
     v_deptno NUMBER; — 변수선언
     v_loc VARCHAR2(20); — 문자저장
begin
    select deptno, loc
    into v_deptno, v_loc
    from dept
    where dname=’ACCOUNTING';
   –출력
    dbms_output.put_line(‘부서번호:’|| v_deptno); — || -> +
    dbms_output.put_line(‘부서위치:’|| v_loc);
end;
/
실행결과
부서번호:10
부서위치:NEW YORK

<문제4> %Type을 배워보자
Ex) 사번 7788인 사원에 대한 부서번호에 따른 부서명을 구하기
declare
   – %type=>필드의 자료형을 정확히 모를때
   – 테이블명.필드명%TYPE
    v_deptno emp.deptno%TYPE; –number
    v_ename emp.ename%TYPE; –VARCHAR2(20);
    v_dept_name VARCHAR2(50); –emp테이블에 dname
begin
    select deptno, ename
    into v_deptno, v_ename
    from emp
    where empno=7788;
   — 제어문
    if (v_deptno=10) then
        v_dept_name:=’ACCOUNTING';
    elsif(v_deptno=20) then
        v_dept_name:=’RESEARCH';
    elsif(v_deptno=30) then
        v_dept_name:=’SALES';
    elsif(v_deptno=40) then
        v_dept_name:=’OPERATION';
    else
        v_dept_name:=’NONE';
    end if;
   –출력
    dbms_output.put_line(‘부서명은 ‘ || v_dept_name);
end;
/
실행화면
부서명은 RESEARCH
=============
<문제5> 반복문->for문
Ex) 숫자 1~9까지의 각각의 제곱수를 구하는 프로그램작성
begin
    for(int i=1;i<=9;i++)
   — for 출력변수 in 초기값..종류값 loop
   — i+”*”+”=”+(i*i)
    for i in 1..9 loop
      dbms_output.put_line(i || ‘*’ || i ||’=’ ||(i*i));
    end loop;
end;
/
실행화면
1*1=1
2*2=4
3*3=9
4*4=16
5*5=25
6*6=36
7*7=49
8*8=64
9*9=81

=============
<문제6> 반복문- loop – end loop;(반복할 횟수가 정해져 있지 않은 경우)
 [exit when 조건식]=> 빠져나갈 조건
출력할 변수를 따로 선언
 테이블에 데이터를 입력시켜주는 프로그램 작성
declare
    v_counter number:=1;
begin
    loop
   — 실행구문
      insert into b_dept values(90+ v_counter, ‘총무’, ‘서울’);
      v_counter:=v_counter+10;
    exit when v_counter > 5;
    end loop;
    commit; — rollback;
 end;
/

실행후 결과값
SQL> select * from b_dept;

    DEPTNO DNAME          LOC
———- ——————- ————-
        10 ACCOUNTING     NEW YORK
        20 RESEARCH          DALLAS
        30 SALES                   CHICAGO
        40 OPERATIONS     BOSTON
        80 IMSI                         Inchon
        90 IMSI2                      SEOUL
        91 총무                                 서울
        60 Testing                       Busan
        70 Testing2                   SEOUL
        50 SUPPORT               Kwamgju

<문제7> %Type(필드하나),%ROWTYPE(행하나), Record(행이상)
Record=> 구조체(서로 다른 자료형을 하나로 묶어준형태)
declare
 type 레코드변수명 is record(구성요소~);
  TYPE emp_record IS RECORD — class emp_record (
  (  v_empno number,                             int v_empno;
     v_ename varchar2(30),             —      String v_ename;
     v_hiredate date                                   Timestamp v_hiredate);
   );
  레코드변수명 레코드자료형;
   emp_rec emp_record;       — emp_record emp_rec=new emp_record();
begin                        
     select empno, ename, hiredate
    into emp_rec.v_empno, emp_rec.v_ename, emp_rec.v_hiredate
    from emp
    where empno=&p_empno;
   — 출력
    dbms_output.put_line(emp_rec.v_empno);
    dbms_output.put_line(emp_rec.v_ename);
    dbms_output.put_line(emp_rec.v_hiredate);
end;
/
실행결과
7902
FORD
81/12/03
<문제8> %ROWTYPE을 이용
Ex) 사번을 입력받아서 사원테이블의 사번, 이름, 입사일자출력?
declare
   행하나 저장
    emp_record emp%ROWTYPE; –테이블명%ROWTYPE;
begin
    select *
    into emp_record
    from emp
    where empno=7788;
   — 출력
    dbms_output.put_line(‘사번:’ || emp_record.empno);
    dbms_output.put_line(‘이름:’ || emp_record.ename);
    dbms_output.put_line(‘입사일:’ || emp_record.hiredate);
end;
/
실행결과
사번:7788
이름:SCOTT
입사일:87/04/19

<문제9> 커서를 이용해서 사원 10명의 사번와 이름순으로 출력하시오
필드(%type) 행(%RowType) or Record(원하는 필드만구성) , 커서(행하나 이상을 메모리상에 저장)
declare
      v_empno emp.empno%TYPE;
      v_ename emp.ename%TYPE;
      1. 커서를 선언 cursor 커서이름 is 
     —            select~
      CURSOR mycursor is
      select empno, ename
      from emp
      order by 1;
begin
    2.open 커서명; (데이터를 불러오기위한 준비단계)
    open mycursor;
   — 출력구문
    dbms_output.put_line(‘사번——–이름’);
    for i in 1..10 loop
        3. FETCH 커서명(레크드를 1개씩 읽어들이는 기능)
        FETCH mycursor
        into v_empno, v_ename;
        dbms_output.put_line(v_empno || ‘—‘ || v_ename);
    end loop;
    4.커서 종료->메모리 해제
    CLOSE mycursor; — CLOSE 닫을 커서명;
end;
/
실행결과
사번——–이름
7369—SMITH
7499—ALLEN
7521—WARD
7566—JONES
7654—MARTIN
7698—BLAKE
7782—CLARK
7788—SCOTT
7839—KING
7844—TURNER

<문제10> 부서번호가 30번인 사원들의 이름과 급여를 조회?
(단 where조건절을 사용하지 말것.  커서(emp_cursor)를 이용할것)
declare
   — 1.커서선언
    CURSOR emp_cursor IS
    select deptno,ename,sal
    from emp;
begin
   2.커서를 불러오자
   — for 단수 in 복수 loop
    for item in emp_cursor loop
       — 조건(부서번호가 30번)
        if item.deptno=30 then
            dbms_output.put_line(‘이름:’|| item.ename);
            dbms_output.put_line(‘급여:’|| item.sal);
        end if;
    end loop;
end;
/
실행결과
이름:ALLEN
급여:1600
이름:WARD
급여:1250
이름:MARTIN
급여:1250
이름:BLAKE
급여:2850
이름:TURNER
급여:1500
이름:JAMES
급여:950

<문제11> 부서번호가 10인 사원들의 이름과 급여를 조회?
(서브쿼리를 사용하는 커서 for루프를 이용하시오.)
select ename,sal from emp where deptno=10; –> SQL문제
begin
     for 단수 in 복수 loop
     — end loop
      for item in (select ename,sal from emp where deptno=10) loop
          dbms_output.put_line(item.ename || ‘—‘ || item.sal);
      end loop;
end;
/
실행결과
CLARK—2450
KING—5000
MILLER—1300

<문제12> while문을 이용해서 b_dept테이블에 5건의 행을 입력하시오
  /* while 조건식 loop
        실행문
     end loop;
  */
declare
    v_max dept.deptno%TYPE; — 부서번호 최대값
    v_counter number:=1;
begin
    select max(deptno)
    into v_max
    from b_dept;
   
    while v_counter < 6 loop
        insert into b_dept
            values(v_max+ v_counter, ‘영업부’,’부산’);
        v_counter := v_counter + 1;
    end loop;
end;
/
실행결과 deptno-> 92,93,94,95,96 등록
 result

<문제13> 프로시저(=메서드) 작성법-> 반환값이 없다.
Ex) 사원번호가 7902번인 사원번호를 외부에서 입력받고 급여를 10%인상 시키는 프로시저를 작성하시오.
select sal from emp
where empno=7902; –sal =3000
/*
create or replace procedure 작성할 프로시저명(
    매개변수 in 자료형(%TYPE,number,varchar2,,,),,
)
IS
begin
    실행구문
end;
/
*/
create or replace procedure myProcedure
(
    pid in emp.empno%TYPEpublic void myProcedure(int pid){}
)
IS
begin
    update emp set sal=1.1*sal
    where empno=pid;
end;
/
실행결과
procedure myProcedure이(가) 컴파일되었습니다.
execute myprocedure(7902)
select sal from emp where empno=7902;
실행결과
sal
——
3300

<문제14> 함수사용하기-> 매개변수 0, 반환값 0
Ex) 부서번호를 입력받아서 부서급여의 총금액을 구해주는 함수를 작성하시오
select deptno, sum(sal)
from emp
group by deptno;
/*
create or replace function 작성할 함수명(
  매개변수 in 자료형 –public 자료형 메서드명(~){
                         return 자료형변수
                           –}
)
return 자료형
is
begin

end;
/
*/
create or replace function myFunction
(
    pdeptno in emp.deptno%TYPE
)
return NUMBER
is
— 변수가 필요하면 이부분에 선언
  v_sum number;
begin
    select sum(sal)
    into v_sum
    from emp
    where deptno=pdeptno;
    return v_sum; — return 결과값;
end;
/
실행결과
function myFunction이(가) 컴파일되었습니다.
select myfunction(30) from dual;
MYFUNCTION(30)
——————-
        9400

<문제15> emp테이블에서 모든 사원의 평균급여를 구해주는 함수를 작성하시오
(getAvgSalary)
create or replace function getAvgSalary
return NUMBER
is
  v_avg NUMBER:=0 — 평균값을 저장할 변수
begin
  select avg(sal)
  into v_avg
  from emp;
  return v_avg;
end;
/
실행결과
function getAvgSalary이(가) 컴파일되었습니다.
select round(getAvgSalary) from dual;
Round(getavgsalary)
———————-
          2116
<문제16> getMax함수를 작성 -> 매개변수 X
Ex) emp테이블에서 최대급여?-> v_max
create or replace function getMax
return NUMBER
is
  v_max NUMBER :=0; — 최대값을 저장하는 변수
begin
  select max(sal)
  into v_max
  from emp;
  return v_max;
end;
/
실행결과
function getMax이(가) 컴파일되었습니다.
select getMax from dual;
GETMAX
———
5000

<문제17> 데이터를 입력시켜주는 프로시저작성
create table mem(
    num number,
    name varchar2(20),
    sex varchar2(10));
insert into mem values(1,’홍길동’,’남자’);
select max(num) from mem;
select * from mem;

============================

–함수작성

create or replace function getMax — 위에 있는거 수정
return NUMBER
is
  v_max NUMBER :=0; 
begin
  select max(num)+1 — 자동 카운팅됨
  into v_max
  from mem;
  return v_max;
end;
/
function getMax이(가) 컴파일되었습니다.

–프로시저작성
create or replace procedure AddMember
(
    name in VARCHAR2,
    sex in char
)
is
begin — values(함수명, 입력값, 입력값2…);
  insert into mem values(getmax, name, sex);
  commit;
end;
/
procedure AddMember이(가) 컴파일되었습니다.
exec AddMember(‘테스트’,’남자’);
exec AddMember(‘임시’,’여자’);
select * from mem;
   NUM      NAME                    SEX
———- ——————– ———-
      1       홍길동                    남자
      2       테스트                    남자
      3        임시                      여자
==============================
<과제> 사원이름
부서별 사원수와 급여합계를 구하시오. (커서를 작성(dept_sum)-> for in 구문)
select b.dname,count(a.empno) cnt, sum(a.sal) salary
from emp a, dept b
where a.deptno=b.deptno
group by b.dname;

<출력결과>
부서명 — 사원수 — 급여총합
ACCOUN     3             8750

begin
      dbms_output.put_line(‘부서명’ || ‘—‘ || ‘사원수’ || ‘—‘ || ‘급여총합’);
      for item in (select b.dname as dname,count(a.empno) cnt, sum(a.sal) salary
                       from emp a, dept b where a.deptno=b.deptno
                       group by b.dname) loop
         
          dbms_output.put_line(item.dname || ‘   ‘ || item.cnt || ‘   ‘ || item.salary);
      end loop;
end;
/

실행결과

부서명—사원수—급여총합
ACCOUNTING   3   8750
RESEARCH   5   11475
SALES   6   9400

<과제 풀이> ->강사님
set serveroutput on
declare

     CURSOR dept_sum IS
     select b.dname,count(a.empno) cnt,
     sum(a.sal) salary
     from emp a,dept b
     where a.deptno=b.deptno
     group by b.dname;
begin
   dbms_output.put_line
     (‘부서명’||’—‘||’사원수’||’–‘||’급여총합’);
   for item in dept_sum loop
   dbms_output.put_line
(item.dname ||’—‘||item.cnt||’—‘||item.salary);
   end loop;
end;
/

실행결과

부서명—사원수–급여총합
ACCOUNTING—3—8750
RESEARCH—5—11475
SALES—6—9400