강의목표

1. PL/SQL의 문법을 이해하고 실행할 수 있다. - FOR LOOP

 

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

[형식]
FOR 변수 IN 초기값..최종값 LOOP
    명령문;
END LOOP;

[형식]
LOOP ~무한 반복 명령~ END LOOP;  -- EXIT로 탈출

ACCEPT 변수 PROMPT '출력문장' -> 사용자 입력라인 값을 읽어서 변수에 저장 %TYPE
===========================================================================
PROCEDURE 프로시져란?
  - 특정 작업을 수행할 수 있고 이름이 있는 PL/SQL 블록으로서 매개변수를 받을 수도 있고
    반복적으로 사용할 수도 있다.

  - 보통 연속실행 또는 구현이 복잡한 트랜잭션을 수행하는 PL/SQL 블록을
    DB에 저장하기 위해서 생성한다.

트랜잭션 : 작업의 단위, 일련의 작업 등을 하나의 프로세서(EXE)로 취하는 것

CREATE PROCEDURE p_name(
                        IN args    -- 실행환경에서 값을 전달
                     OUT args    -- 값을 리턴
                 IN OUT args    -- 전달, 리턴한다.
)
IS
    변수 선언
BEGIN
    구문
END p_name;

예시)
CREATE PROCEDURE update_sal(v_empno in number)
IS
BEGIN
    UPDATE EMP SET SAL = SAL + 100
    WHERE EMPNO = v_empno;
    COMMIT;
END update_sal;
/    -- 생성완료

EXECUTE UPDATE_SAL(7369);    -- 프로시져 실행
EXEC UPDATE_SAL(7369); 


만들어진 STORED PROCEDURE LIST 보기
SELECT * FROM USER_PROCEDURES;


프로시저의 내용까지 확인
SELECT * FROM USER_SOURCE;


SELECT OBJECT_NAME, STATUS
FROM USER_OBJECTS
WHERE OBJECT_TYPE = 'VIEW';    -- WHERE OBJECT_TYPE = 'PROCEDURE';


SELECT OBJECT_NAME, STATUS
FROM USER_OBJECTS
WHERE OBJECT_TYPE = 'PROCEDURE';

============================================================================
FUNCTION 함수는 매개변수로 IN만 가능하다. 그 대신 RETURN이라는 키워드가 존재
그것이 프로시져랑 차이점

var res_sal number;    --  변수 선언

EXECUTE :res_sal := fc_update_sal(7369);    -- 함수 호출 시 리턴하는 값을 대입 후 실행

PRINT RES_SAL;    -- 내용 출력

============================================================================
예제)
type MY_REC is record (v_empno number,
                               v_ename varchar2(30),
                               v_hiredate date);
empr MY_REC;

~~ INTO empr.v_empno, empr.v_ename, empr.v_hiredate
from emp;

============================================================================
Q1) 1에서 10까지 반복하여 TEST1 테이블에 저장하라 (for문 사용)
SET SERVEROUTPUT ON

CREATE TABLE TEST1(bunho NUMBER(3),
                            irum VARCHAR2(10));

BEGIN
  for i in 1..10 loop
    INSERT INTO TEST1 VALUES (i, sysdate);
  end loop;
END;

SELECT * FROM TEST1;


Q2) 1~50까지 출력하자 [ 현재의 i값은 ? 00이다 ]  -> FOR LOOP
DECLARE
    i int := 0;
BEGIN
    FOR i IN 1..50 LOOP
        DBMS_OUTPUT.PUT_LINE('현재의 i 값은?  ' || i || ' 이다');
    END LOOP;
END;
/


Q3) 구구단에서 홀수 단만 출력해보자
DECLARE
    total number := 0;
BEGIN
    FOR i IN 2..9 LOOP
        IF MOD(i, 2) <> 0 THEN
            DBMS_OUTPUT.PUT_LINE(i || ' 단');

            FOR j IN 2..9 LOOP
                total := i*j;
                DBMS_OUTPUT.PUT_LINE(i || ' * ' || j || ' = ' || total);
            END LOOP;
            DBMS_OUTPUT.PUT_LINE('=========================');
        END IF;
    END LOOP;
END;
/


Q4) 1 ~ 50 출력해보자
DECLARE
    i int := 1;
BEGIN
    LOOP
        DBMS_OUTPUT.PUT_LINE('현재 i 값은  ' || i || '  입니다');
        i := i + 1;
        IF i > 50 THEN
            EXIT;
        END IF;
    END LOOP;
END;
/


Q5) EMP 테이블에서 부서번호 10인 사원 평균 급여를 출력하는 익명의 블록을 완성해보자.
SELECT AVG(SAL) FROM EMP WHERE DEPTNO=10 GROUP BY DEPTNO;

DECLARE
    avg01 NUMBER(7) := 0;
    deptno01 NUMBER(7) := 10;
BEGIN
    SELECT AVG(SAL) INTO avg01
    FROM EMP
    WHERE DEPTNO = deptno01
    GROUP BY DEPTNO;
    DBMS_OUTPUT.PUT_LINE(deptno01 || ' 번 부서의 평균 급여는 [ ' || avg01 || ' ] 원 입니다.');
END;
/

Q6) 20번 부서에 [5]명에 대한 평균 급여는 [2175]원이다. 익명으로 풀어보자.
     EMP 테이블에서 20번 부서의 개수, 평균 급여를 구하자.
SELECT COUNT(*), AVG(SAL) FROM EMP WHERE DEPTNO=20 GROUP BY DEPTNO;

DECLARE
    DNO NUMBER := 20;
    CNT NUMBER := 0;
    AVG_SAL NUMBER := 0;
BEGIN
    SELECT COUNT(*), AVG(SAL) INTO CNT, AVG_SAL
              FROM EMP WHERE DEPTNO=DNO GROUP BY DEPTNO;
    DBMS_OUTPUT.PUT_LINE('20번 부서 ' || CNT || ' 명에 대한 평균 급여는 ' || AVG_SAL || ' 원 입니다.');
END;
/


Q7) 사번을 입력해서 이름을 리턴받자.
ACCEPT INPUT_VAL
7902

DECLARE
    MY_NAME EMP.ENAME%TYPE;
BEGIN
    SELECT ENAME  INTO MY_NAME
    FROM EMP
    WHERE EMPNO = &INPUT_VAL;
    DBMS_OUTPUT.PUT_LINE('현재의 결과는 ' || MY_NAME);
END;
/


Q8) 30번 부서의 인원수는 [6]이고 평균급여 [777]이다. [D]등급이다.
조건 : 2500 이상이면 'A'
         2000 이상이면 'B'
         1500 이상이면 'C'
         1000 이상이면 'D'
                             'F'

ACCEPT DNO

DECLARE
    CNT NUMBER := 0;
    AVG_SAL NUMBER := 0;
    GRADE CHAR(1) := '';
BEGIN
    SELECT COUNT(*), AVG(SAL) INTO CNT, AVG_SAL
    FROM EMP 
    WHERE DEPTNO=&DNO 
    GROUP BY DEPTNO;

    IF AVG_SAL >= 2500 THEN GRADE := 'A';
        ELSIF AVG_SAL >= 2000 THEN GRADE := 'A';
        ELSIF AVG_SAL >= 1500 THEN GRADE := 'C';
        ELSIF AVG_SAL >= 1000 THEN GRADE := 'D';
        ELSE GRADE := 'F';
    END IF;

    DBMS_OUTPUT.PUT_LINE(&DNO || '부서의 인원수는 ' || CNT || '명 이다.');
    DBMS_OUTPUT.PUT_LINE('평균 급여는 ' || ROUND(AVG_SAL) || ' 원 이고, ' || GRADE || ' 등급이다.');
END;
/


Q9) 부서번호를 입력받아 사원의 번호, 이름 급여, 직업을 출력하는 프로시져 만들기
CREATE OR REPLACE PROCEDURE EX_PRO05( P_EMPNO IN EMP.EMPNO%TYPE)
AS
    V_EMP EMP%ROWTYPE;    -- 한 줄의 레코드 타입이 지정된다.
BEGIN
    SELECT EMPNO, ENAME, SAL, JOB INTO V_EMP.EMPNO, V_EMP.ENAME, V_EMP.SAL, V_EMP.JOB
    FROM EMP
    WHERE EMPNO = P_EMPNO;

    DBMS_OUTPUT.PUT_LINE(V_EMP.EMPNO);
    DBMS_OUTPUT.PUT_LINE(V_EMP.ENAME);
    DBMS_OUTPUT.PUT_LINE(V_EMP.SAL);
    DBMS_OUTPUT.PUT_LINE(V_EMP.JOB);
END EX_PRO05;


Q10) 사번을 입력받아서 월급에 100을 더하는 함수를 작성해보자
CREATE OR REPLACE FUNCTION FC_UPDATE_SAL(v_empno emp.empno%type)
RETURN NUMBER 
AS
    v_sal emp.sal%type;
BEGIN
    UPDATE EMP SET SAL = SAL + 100
    WHERE EMPNO = v_empno;
    COMMIT;

    SELECT SAL INTO v_sal
    FROM EMP
    WHERE EMPNO = v_empno;

    RETURN v_sal;
END FC_UPDATE_SAL;

var res_sal number;    --  변수 선언

EXECUTE :res_sal := fc_update_sal(7369);    -- 함수 호출 시 리턴하는 값을 대입 후 실행

PRINT RES_SAL;    -- 내용 출력


Q11) 사번을 입력받아 연봉을 계산(SAL*12 + COMM)해서 출력하는 함수를 작성하고 다음 문장을 실행
SELECT EMPNO, EX_GET_SAL(EMPNO) FROM EMP;

CREATE OR REPLACE FUNCTION EX_GET_SAL (V_ID EMP.EMPNO%TYPE)
RETURN NUMBER 
AS 
    GET_SAL NUMBER := 0;
BEGIN
    SELECT SAL*12+NVL(COMM,0) INTO GET_SAL
    FROM EMP
    WHERE EMPNO = V_ID;
    RETURN GET_SAL;
END EX_GET_SAL;


Q12) 사번을 입력받아 사원번호 사원이름 입사일을 출력하는 프로시져를 만들고 다음 문장을 실행
EXEC EX_PRO06(7369);

CREATE OR REPLACE PROCEDURE EX_PRO06 (ENO NUMBER)
AS 
    E_NAME VARCHAR2(20) := ' ';
    E_DATE DATE := SYSDATE;
BEGIN
    SELECT ENAME, HIREDATE INTO E_NAME, E_DATE
    FROM EMP
    WHERE EMPNO = ENO;
    
    DBMS_OUTPUT.PUT_LINE('사원번호 : ' || ENO);
    DBMS_OUTPUT.PUT_LINE('사원이름 : ' || E_NAME);
    DBMS_OUTPUT.PUT_LINE('입사일 : ' || E_DATE);
END EX_PRO06;

'데이터과학자 - 강의 > oracle' 카테고리의 다른 글

210602 oracle - CURSOR  (0) 2021.06.02
210531 oracle - CONSTRAINT, SEQUENCE  (0) 2021.05.31
210526 oracle - CONSTRAINT, SEQUENCE  (0) 2021.05.28
210526 oracle - Transaction, TCL, DDL  (0) 2021.05.27
210526 oracle - DML  (0) 2021.05.26

+ Recent posts