16.PL/SQL
by SANGGI JEON
PL/SQL
ORACLE에서 SQL언어를 확장해서 사용하는 프로그래밍 언어
- PL/SQL ON
>set serveroutput on
- 변수 선언
DECLARE
V_NO NUMBER(4);
V_NAME VARCHAR2(20);
DECLARE
V_EMPNO EMP.EMPNO%TYPE;
V_SAL EMP.SAL%TYPE;
- 코드 블럭
BEGIN
SELECT EMPNO, ENAME
INTO V_NO, V_NAME
FROM EMP
WHERE EMPNO = 7369;
DBMS_OUTPUT.LINE(V_NO || '' || V_NAME);
END;
/
1. PL/SQL 예제
- &ID는 id 값을 입력 받을 수 있음
DECLARE
V_EMPNO EMP.EMPNO%TYPE;
V_SAL EMP.SAL%TYPE;
BEGIN
SELECT EMPNO, SAL
INTO V_EMPNO, V_SAL
FROM EMP
WHERE EMPNO = &ID;
DBMS_OUTPUT.PUT_LINE(V_EMPNO || ' ' || V_SAL);
END;
/
2. 커서
- 특정 SQL 문장을 처리한 결과를 담고있는 영역을 가리키는 일종의 포인터
- 커서를 사용하면 처리된 SQL문장의 결과 집합에 접근할 수 있음
2.1 묵시적 커서
- 오라클 내부에서 자동으로 생성되어 사용하는 커서
- PL/SQL 블럭에서 DML 문장이 실행될 때마다 자동으로 생성
2.1.1 묵시적 커서 예제
- SQL%FOUND : 결과집합의 패치 ROW수가 1개 이상 TRUE, 아니면 FALSE
- SQL%NOTFOUND : 결과집합의 패치 ROW수가 0이면 TURE, 아니면 FALSE
- SQL%ROWCOUNT : 영향받은 결과 집합 ROW수, 없으면 0
- SQL%ISOPEN : 묵시적 커서는 항상 FALSE(묵시적 커서는 실행문 종료 후 바로 닫힘)
2.2 명시적 커서
DECLARE
V_DEPARTMENT_ID EMPLOYEES.DEPARTMENT_ID%TYPE := 80;
BEGIN
UPDATE EMPLOYEES
SET FIRST_NAME = FIRST_NAME
WHERE DEPARTMENT_ID = V_DEPARTMENT_ID;
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT);
COMMIT;
END;
/
DECLARE
V_DEPTNO EMP.DEPTNO%TYPE := 20;
BEGIN
UPDATE EMP
SET ENAME = 'MR.' || ENAME
WHERE DEPTNO = V_DEPTNO;
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT);
COMMIT;
END;
/
3. 반복문
DECLARE
CURSOR CUR_EMP
IS
SELECT (FIRST_NAME || ' '|| LAST_NAME) AS "FULL_NAME"
FROM EMPLOYEES
WHERE DEPARTMENT_ID IN (100, 110);
EMP_FULL_NAME EMPLOYEES.FIRST_NAME%TYPE;
BEGIN
OPEN CUR_EMP;
LOOP
FETCH CUR_EMP INTO EMP_FULL_NAME;
EXIT WHEN CUR_EMP%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(EMP_FULL_NAME);
END LOOP;
CLOSE CUR_EMP;
END;
/
4. 함수
CREATE OR REPLACE FUNCTION FN_GET_SALARY
(IN_EMPNO EMP.EMPNO%TYPE)
RETURN EMP.SAL%TYPE
IS
OUT_SAL EMP.SAL%TYPE :=0;
BEGIN
SELECT SAL
INTO OUT_SAL
FROM EMP
WHERE EMPNO = IN_EMPNO;
RETURN OUT_SAL;
END;
/
- 함수 삭제
DROP FUNCTION FN_GET_SALARY
5. 저장 프로시저(Stored-Procedure)
- 함수는 반드시 리턴이 있어야 함
- 저장 프로시저는 리턴이 없어도 됨
CREATE OR REPLACE PROCEDURE SP_GET_SALARY(
IN_EMPLOYEE_ID IN EMPLOYEES.EMPLOYEE_ID%TYPE,
OUT_SALARY OUT EMPLOYEES.SALARY%TYPE
)
IS
BEGIN
SELECT SALARY
INTO OUT_SALARY
FROM EMPLOYEES
WHERE EMPLOYEE_ID = IN_EMPLOYEE_ID;
END;
DECLARE OUT_SALARY EMPLOYEES.SALARY%TYPE;
BEGIN
SP_GET_SALARY('101', OUT_SALARY);
DBMS_OUTPUT.PUT_LINE(OUT_SALARY);
END;
- 작성한 프로시저 확인 법
SELECT object_name, object_type
FROM user_objects
WHERE object_type = 'PROCEDURE'
6. REF CURSOR
-
패키지가 필요하기 때문에 패키지 생성이 필요
-
패키지 해더 작성
CREATE OR REPLACE PACKAGE CURSOR_PKG
AS
TYPE T_CURSOR IS REF CURSOR;
PROCEDURE SP_JOB_HISTORY(
IN_EMPLOYEE_ID IN EMPLOYEES.EMPLOYEE_ID%TYPE,
OUT_CURSOR IN OUT T_CURSOR
);
END CURSOR_PKG;
/
- 패키지 바디 생성
CREATE OR REPLACE PACKAGE BODY CURSOR_PKG
AS
PROCEDURE SP_JOB_HISTORY
(
IN_EMPLOYEE_ID IN EMPLOYEES.EMPLOYEE_ID%TYPE,
OUT_CURSOR IN OUT T_CURSOR
)
IS
BEGIN
OPEN OUT_CURSOR FOR
SELECT E.FIRST_NAME || ' ' || E.LAST_NAME AS NAME,
JO.JOB_TITLE AS TITLE,
JH.START_DATE AS SDATE,
JH.END_DATE AS EDATE
FROM EMPLOYEES E JOIN JOB_HISTORY JH
ON E.EMPLOYEE_ID = JH.EMPLOYEE_ID
JOIN JOBS JO
ON JH.JOB_ID = JO.JOB_ID
WHERE E.EMPLOYEE_ID = IN_EMPLOYEE_ID;
END SP_JOB_HISTORY;
END CURSOR_PKG;
/
DECLARE
TYPE T_CURSOR IS REF CURSOR;
RET_CUR T_CURSOR;
RET_NAME VARCHAR2(50);
RET_TITLE VARCHAR2(50);
RET_SDATE DATE;
RET_EDATE DATE;
BEGIN
CURSOR_PKG.SP_JOB_HISTORY('200', RET_CUR);
LOOP
FETCH RET_CUR INTO RET_NAME, RET_TITLE, RET_SDATE, RET_EDATE;
EXIT WHEN RET_CUR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(RET_NAME || ',' || RET_TITLE || ',' || RET_SDATE || ',' || RET_EDATE);
END LOOP;
CLOSE RET_CUR;
END;
/
Subscribe via RSS