테이블 함수

  • 여러 로우를 가진 컬렉션을 반환하는 함수
    • 컬렉션 타입을 반환, 연관 배열은 반환하지 못하고 중첩 테이블이나 VARRAY만 반환 가능
  • 기본 함수는 하나의 값만 반환이 가능하지만 테이블 함수로는 여러 행, 열의 반환이 가능
    • Oracle Table Function은 Multi Column + Multi Row로 값을 return할 수 있는 PL/SQL Function

 

문법

  • 일반 함수와 다를 건 없지만, 대상이 되는 컬렉션 타입이 먼저 만들어져 있어야 함.
  • 다음 예시는 DEPT와 EMP 테이블을 예를 들어, DEPT 번호를 파라미터로 전달하여 부서 및 직원 정보를  가져오는 쿼리를 TABLE 함수 형태로 변환
  1. OBJECT 타입 생성
    1. 행을 리턴받는 역할
    2. 함수에서 반환하는 레코드의 스키마
  2. (임시) TABLE TYPE 객체 생성
    1. 함수에서 반환하는 레코드의 집합(테이블) 정의
  3. Table Function 생성 (테이블 Return)
  4. "Table" 키워드를 사용하여 조회

 

예시

-- 1. OBJECT 타입 생성 
CREATE OR REPLACE TYPE DEPT_TYPE AS OBJECT ( 
	DEPTNO NUMBER(2), 
	DNAME VARCHAR2(14), 
	LOC VARCHAR2(13), 
	EMPNO NUMBER(4), 
	ENAME VARCHAR2(10) 
)

 

-- 2. TABLE 타입 생성 
CREATE OR REPLACE TYPE DEPT_TABLE AS TABLE OF DEPT_TYPE;

 

-- 3. 함수 생성 (테이블 리턴) 
CREATE OR REPLACE FUNCTION GET_DEPT_FN(P_DEPT_NO IN NUMBER) 
	RETURN DEPT_TABLE 
IS 
	V_RSLT DEPT_TABLE; 
BEGIN 
	SELECT DEPT_TYPE(A.DEPTNO, A.DNAME, A.LOC, B.EMPNO, B.ENAME) 
	BULK COLLECT INTO V_RSLT 
	FROM DEPT A , EMP B 
	WHERE A.DEPTNO = B.DEPTNO 
	AND A.DEPTNO = P_DEPT_NO; 
	RETURN V_RSLT; 
END GET_DEPT_FN;

 

-- 실행예시 
SELECT * FROM TABLE(GET_DEPT_FN(30));

 

 

Pipelined Table Function

  • Table Function과 거의 유사, 한 행 단위로 바로바로 즉시 값을 리턴하는 함수
  • 한 Row씩 처리하므로 결과값들이 바로 출력되기 시작
  • Oracle 9i부터 사용
  1. OBJECT 타입 생성
  2. (임시) TABLE TYPE 객체 생성
  3. Pipelined Table Function 생성
  4. 조회
-- 1. OBJECT 타입 생성 
CREATE OR REPLACE TYPE DEPT_TYPE AS OBJECT ( 
	DEPTNO NUMBER(2), 
	DNAME VARCHAR2(14), 
	LOC VARCHAR2(13), 
	EMPNO NUMBER(4), 
	ENAME VARCHAR2(10) 
)

 

-- 2. TABLE 타입 생성 
CREATE OR REPLACE TYPE DEPT_TABLE AS TABLE OF DEPT_TYPE;

 

-- 3. Pipelined 함수 생성 (테이블 리턴) 
CREATE OR REPLACE FUNCTION GODDAEHEE.GET_DEPT_PIPE_FN(P_DEPT_NO IN NUMBER) 
	RETURN DEPT_TABLE 
	PIPELINED 
IS 
	V_RSLT DEPT_TYPE; 
BEGIN 
	FOR DEPT_CUR IN ( 
	SELECT A.DEPTNO, A.DNAME, A.LOC, B.EMPNO, B.ENAME 
	FROM DEPT A 
		, EMP B 
	WHERE A.DEPTNO = B.DEPTNO 
	AND A.DEPTNO = P_DEPT_NO 
	) 
	LOOP 
		V_RSLT := DEPT_TYPE(DEPT_CUR.DEPTNO, DEPT_CUR.DNAME, DEPT_CUR.LOC, DEPT_CUR.EMPNO, DEPT_CUR.ENAME); 
		PIPE ROW(V_RSLT); 
	END LOOP; 
	RETURN; 
END;

 

-- 실행예시 
SELECT * FROM TABLE(GET_DEPT_PIPE_FN(30));

'Study > Oracle' 카테고리의 다른 글

PL/SQL 기본_5 - 함수  (0) 2021.05.17
PL/SQL 기본_4 - 프로시저  (0) 2021.05.10
PL/SQL 기본_3 - 커서  (0) 2021.05.10
PL/SQL 기본_2 - 반복문과 제어문  (0) 2021.05.10
PL/SQL 기본_1  (0) 2021.05.10

함수

  • 특정 기능들을 모듈화, 재사용할 수 있어서 복잡한 쿼리문을 간결하게 만듬
    • 함수 사용이 쿼리 속도를 느리게 만드는 원인이 될 수 있으니 필요한 경우만 사용
  • 호출한 곳으로 반드시 하나의 값을 리턴해야 하는 PL/SQL Stored Program
    • 즉, PL/SQL 블록 내에서 RETURN문을 통해 반드시 값을 리턴
  • 프로시저는 PL/SQL문으로 실행, 함수는 식의 일부로서 사용
  • RETURN 절에 지정된 것과 동일한 데이터 타입으로 RETURN 값을 설정해야 함
  • 함수 작성 시 권한 필요
    • 자신의 스키마 : CREATE PROCEDURE 권한
    • 다른 사용자의 스키마 : CREATE ANY PROCEDURE 권한
  • 기본적으로 DML(INSERT/UPDATE/DELETE)문 사용 불가

함수 기본 문법

CREATE [OR REPLACE] FUNCTION function_name [(
	
	argument...
	
)]
RETURN datatype -- 반환되는 값의 datatype
    IS [AS]
        [선언부]
    BEGIN
        [실행부 - PL/SQL Block]
    [EXCEPTION]
        [EXCEPTION 처리]
    RETURN 변수; -- 리턴문 필수
END;
  • [] : 대괄호 안의 구문은 생략 가능함을 의미
  • OR_REPLACE : 함수생성 DDL 명령어 / 이미 존재하는 함수라면 기존 내용 지우고 재생성, 생략 가능
  • function_name : 사용자 지정 함수명
  • argument : 매개변수1, 매개변수2, 매개변수3 ... 매개변수 선언
  • datatype : VARCHAR2, NUMBER, DATE 등 반환할 데이터 타입 지정

 

함수 작성 및 사용 예시

  • 함수 작성 예시
CREATE OR REPLACE FUNCTION FN_GET_DEPT_NAME( 
	P_DEPT_NO IN VALCHAR2 
) RETURN VARCHAR2 
IS 
	V_TEST_NAME VARCHAR2(10); 
BEGIN 
	SELECT DELP_NAME 
	INTO V_TEST_NAME 
	FROM DEPT 
	WHERE DEPT_NO = P_DEPT_NO; 
RETURN V_TEST_NAME; 
END;

 

  • 함수 사용 예시
    • SELECT 문에서 편하게 사용 가능
SELECT FN_GET_DEPT_NAME('01') FROM DUAL;

'Study > Oracle' 카테고리의 다른 글

PL/SQL_6 - 테이블 함수  (0) 2021.05.18
PL/SQL 기본_4 - 프로시저  (0) 2021.05.10
PL/SQL 기본_3 - 커서  (0) 2021.05.10
PL/SQL 기본_2 - 반복문과 제어문  (0) 2021.05.10
PL/SQL 기본_1  (0) 2021.05.10

저장 프로시저

  • 정의
    • Transact-SQL 문장의 집합
  • 용도
    • 어떠한 동작을 절차적 일괄처리 작업하는 데 사용
    • SQL Server에서 사용하는 프로그래밍 기능
  • 특징
    • SQL Server의 성능 향상(첫 실행 시 컴파일, 재컴파일 안 함)
    • 모듈식 프로그래밍 가능
    • 보안 강화(저장 프로시저마다 권한 할당 가능)
    • 네트워크 전송량 감소(긴 쿼리 문장의 단순화)
  • 장점
    • 빠르다
    • 파라미터 사용 가능
    • 여러 애플리케이션과 공유 가능
  • 기본 문법
    • (인수 없는)프로시저 생성 방법
	CREATE OR REPLACE PROCEDURE 프로시저이름 
	IS
	[
	변수이름 데이터타입;  -- 프로시저내에서 사용할 변수선언
	변수이름 데이터타입;
	변수이름 데이터타입;
	..
	]
	BEGIN
	 기능 구현;
	END;

 

 

  • EX) 인수없는 프로시저
	SET SERVEROUTPUT ON; 
	CREATE OR REPLACE PROCEDURE p_test 
	IS 
		I_MESSAGE VARCHAR2(100) := 'https://pdache.tistory.com'; 
	BEGIN 
		dbms_output.put_line(I_MESSAGE); 
	END; 
	EXEC p_test; --프로시저 호출

 

  • (인수 있는) 프로시저 생성 방법
	CREATE OR REPLACE PROCEDURE 프로시저이름(
	변수이름 IN 데이터타입, 변수이름 IN 데이터타입, .... --IN 생략가능
	)
	IS
	[
	변수이름 데이터타입;  -- 프로시저내에서 사용할 변수선언
	..
	]
	BEGIN
	기능 구현;
	END;

 

  • EX) 인수 있는 프로시저
	CREATE OR REPLACE PROCEDURE p2_test( p_name IN VARCHAR2 ) 
	IS 
	BEGIN 
		dbms_output.put_line(p_name||' 님 안녕하세요?'); 
	END; 
	EXEC p2_test; --프로시저 호출 (오류발생 ) 
		-- (프로시저에 in이 있으면서 기본값이 없기 때문에 반드시 인수값 필요함) 
	EXEC p2_test('Pdache');

 

※인수의 타입 선언 부분 정리

  • IN => 내부 프로그램에 제공
        변수이름 IN VARCHAR2;  -- 인수선언할 때 byte 수 지정안함(인수는 크기를 주지 않음)
        변수이름 IN 테이블이름.컬럼명%TYPE;
        변수이름 IN 테이블이름.컬럼명%TYPE:=값;
        변수이름 IN 테이블이름.컬럼명%TYPE DEFAULT 값;

 

  • OUT => 호출자에게 제공
    • 프로시저 실행 시점에 OUT 매개변수를 변수 형태로 전달하고, 프로시저 실행부에서 이 매개변수에 특정 값을 할당
        변수이름 IN VARCHAR2;
        변수이름 IN 테이블이름.컬럼명%TYPE;

 

  • IN OUT => 입력과 동시에 출력용으로 사용할 수 있다.
        변수이름 IN VARCHAR2;
        변수이름 IN 테이블이름.컬럼명%TYPE;

 

※ IN OUT, OUT 모드로 선언된 파라미터에는 DEFAULT를 적용할 수 없다.

 

 

  • 프로시저 호출 방법
	EXEC 프로시저이름; -- 인수없는 경우 호출
	EXEC 프로시저이름(값, 값, ...);  - 인수있는 경우 호출

 

  • 저장된 프로시저 찾기
    • 작성된 프로시저를 찾기 위해 데이터 사전을 이용할 수 있다.
    • 데이터 사전은 대문자로 값을 저장하기 때문에 대문자로 검색한다.
SELECT * FROM user_objects WHERE object_type = 'PROCEDURE';
SELECT * FROM user_source WHERE name = '프로시저명';

 

  • 프로시저 output 매개변수 사용하기
    • 웹 개발을 하면서 프로시저 결과 핸들링을 위해 많이 사용
    • 프로시저를 실행하여 특정 결과 값을 OUT 변수에 저장하여 보냄
    • OUT 있는 프로시저 작성방법
	CREATE OR REPLACE PROCEDURE 프로시저이름 (
	변수이름 IN 데이터타입, 변수이름 IN 데이터타입, .... --in 생략가능
	변수이름 OUT 데이터타입, 변수이름 OUT 데이터타입 ... --프로시저를 호출하는곳으로 값을 보낸다.
	)
	IS
	[
	변수이름 데이터타입;  -- 프로시저내에서 사용할 변수선언
	..
	]
	BEGIN
	기능 구현;
	END;

 

 

  • EX) 이름을 OUTPUT 해주는 프로시저
	CREATE OR REPLACE PROCEDURE p_outTest(
		p_NAME OUT VARCHAR2
	)
	IS
	BEGIN
		p_NAME := 'Pdache';
	    DBMS_OUTPUT.PUT_LINE('호출 완료');
	END;
	--out이 있는 프로시저 호출방법
	--DECLARE 로 선언되변수는 일회용
	
	DECLARE
	OUT_MSG VARCHAR2(2000);
	
	BEGIN
	p_outTest(OUT_MSG);  -- 프로시저를 실행 한후에 out을 받을 변수지정
	dbms_output.put_line(OUT_MSG); -- 출력하기
	END;

'Study > Oracle' 카테고리의 다른 글

PL/SQL_6 - 테이블 함수  (0) 2021.05.18
PL/SQL 기본_5 - 함수  (0) 2021.05.17
PL/SQL 기본_3 - 커서  (0) 2021.05.10
PL/SQL 기본_2 - 반복문과 제어문  (0) 2021.05.10
PL/SQL 기본_1  (0) 2021.05.10

PL/SQL의 꽃이라 불리는 "커서"에 대해서 알아보도록 하자.

 

커서(CURSOR)의 정의

  • SQL 커서는 Oracle 서버에서 할당한 전용 메모리 영역에 대한 포인터이다.
  • 질의의 결과로 얻어진 여러 행이 저장된 메모리 상의 위치
  • 커서는 SELECT문의 결과 집합을 처리하는데 사용

 

커서(CURSOR)의 종류

  • 암시적 커서(Implicit Cursor)
    • 정의
      • 오라클 DB에서 실행되는 모든 SQL 문장은 암시적 커서가 생성되며, 커서 속성을 사용할 수 있다.
      • 모든 DML과 PL/SQL SELECT문에 대해 선언
      • 암시적 커서는 오라클이나 PL/SQL 실행 메커니즘에 의해 처리되는 SQL 문장이 처리되는 곳에 대한 익명의 주소
      • Oracle 서버에서 SQL문을 처리하기 위해 내부적으로 생성하고 관리
      • 암시적 커서는 SQL문이 실행되는 순간 자동으로 OPEN, CLOSE 실행
      • SQL 커서 속성을 사용하면 SQL문 결과 테스트 가능
    • 속성
      • SQL%FOUND : 해당 SQL문에 의해 반환된 총 행수가 1개 이상일 경우 TRUE(BOOLEAN)
      • SQL%NOTFOUND : 해당 SQL문에 의해 반환된 총 행수가 없을 경우 TRUE(BOOLEAN)
      • SQL%ISOPEN : 항상 FALSE, 암시적 커서가 열려 있는지의 여부 검색(PL/SQL은 실행 후 바로 CLOSE)
      • SQL%ROWCOUNT : 해당 SQL문에 의해 반환된 총 행수, 가장 최근 수행된 SQL문에 의해 영향을 받은 행의 갯수(정수)
    • EX)
	SET SERVEROUTPUT ON;
	DECLARE
	    BEGIN
	    DELETE FROM emp WHERE DEPTNO = 10;
	    DBMS_OUTPUT.PUT_LINE('처리 건수 : ' || TO_CHAR(SQL%ROWCOUNT)|| '건');
	    END;

-- 결과

처리 건수 : 21건

PL/SQL 처리가 정상적으로 완료되었습니다.

 

 

  • 명시적 커서(Explicit Cursor)
    • 정의
      • 프로그래머에 의해 선언되어 이름이 있는 커서
    • 속성
      • %ROWCOUNT : 현재까지 반환된 모든 행의 수를 출력
      • %FOUND : FETCH한 데이터가 행을 반환하면 TRUE
      • %NOTFOUND : FETCH한 데이터가 행을 반환하지 않으면 TRUE(LOOP를 종료할 시점을 찾을 때 사용)
      • %ISOPEN : 커서가 OPEN 되어 있으면 TRUE
    • 문법
      • DECLARE를 통해서 명명된 SQL 영역 생성
      • OPEN을 이용하여 결과 행 집합 식별
      • FETCH를 통해 현재 행을 변수에 로드(현재 행이 없을 때까지 수행 가능)
      • CLOSE를 통해 결과 행 집합 해제
	DECLARE
		CURSOR [커서이름] IS [SELECT 구문];
	BEGIN
		OPEN [커서이름];
		FETCH [커서이름] INTO [로컬변수];
		CLOSE [커서이름];
	END;

 

  • OPEN(커서 열기)
    • OPEN 문을 사용하여 커서를 연다.
    • 커서 안의 검색이 실행되며 아무런 데이터 행을 추출하지 못해도 에러가 발생하지 않는다.
  • FETCH(커서 페치)
    • 현재 데이터 행을 OUTPUT 변수에 반환
    • 커서의 SELECT 문의 컬럼 수와 OUTPUT 변수의 수가 동일해야 한다.
    • 커서 컬럼의 변수 타입과 OUTPUT 변수의 데이터 타입 역시 동일해야 한다.
    • 커서는 한 라인씩 데이터를 FETCH
    • 문법 : FETCH cursor_name INTO variable1, variable2;
  • CLOSE(커서 닫기)
    • 사용을 마친 커서는 반드시 닫아준다.
    • 필요시 커서는 다시 열 수 있다.
    • 커서를 닫은 상태에서 FETCH는 불가능하다.
    • 문법 : CLOSE cursor_name;
  • EX 1) 커서 사용 예제 1
	SET SERVEROUTPUT ON;
	DECLARE
	    CURSOR emp_cur -- 커서정의
	    IS
	    SELECT * FROM emp WHERE DEPTNO = 10;
	    emp_rec emp%ROWTYPE; -- 변수정의
	BEGIN
	    OPEN emp_cur;
	    LOOP -- 반복
	    FETCH emp_cur INTO emp_rec; -- 하나씩 변수에 넣기
	    EXIT  WHEN emp_cur%NOTFOUND; -- 더이상 없으면 끝내기
	        DMBS_OUTPUT.PUT_LINE(emp_rec.empno || ' ' || emp_rec.name); -- 출력
	    END LOOP;
	    CLOSE emp_cur;
	END;

 

  • EX 2) 커서 사용 예제 2
	SET SERVEROUTPUT ON;
	DECLARE
	    ID_LIST SYS_REFCURSOR; -- 커서정의
	    I_ID VARCHAR2(100); -- 변수정의
	BEGIN
	    OPEN ID_LIST;
	    FOR
	        SELECT USER_ID FROM MY_USER WHERE 조건;
	    LOOP -- 반복
	    FETCH ID_LIST INTO I_ID; -- 하나씩 변수에 넣기
	    EXIT  WHEN ID_LIST%NOTFOUND; -- 더이상 없으면 끝내기
	        DMBS_OUTPUT.PUT_LINE(I_ID); -- 출력
	    END LOOP;
	    CLOSE ID_LIST;
	END;

 

  • EX 3) 커서 사용 예제 3
	SET SERVEROUTPUT ON;
	DECLARE
	    CURSOR ID_LIST IS
	    SELECT 'GOD' AS USER_ID FROM DUAL;
	BEGIN
	    FOR TEST_CURSOR IN ID_LIST
	    LOOP
	        DBMS_OUTPUT.putline(TEST_CURSOR.USER_ID);
	    END LOOP;
	END;

 

  • 명시적 커서 FOR LOOP
    • 서브 쿼리를 활용하여 CURSOR FOR LOOP를 사용하면 CURSOR를 선언할 필요도 없어진다.
    • 명시적 커서 FOR LOOP를 사용하면 FOR LOOP가 자동적으로 커서를 OPEN, 행이 없을 때까지 FETCH하고, CLOSE
    • ROWTYPE에 해당하는 변수를 따로 DECLARE할 필요가 없다. - 암시적으로 선언되기 때문
    • 이 암시적 카운터는 FOR LOOP에서만 사용 가능
    • 이 커서의 데이터 타입(컬럽 데이터 타입의 집합)도 %ROWTYPE 앞으로 이용 가능
  • EX 3) 커서 사용 예제 3을 "명시적 커서 FOR LOOP" 방식으로 변경한 예
	SET SERVEROUTPUT ON;
	DECLARE
	BEGIN
	    FOR ID_LIST IN 
	    (
	        SELECT 'GOD' AS USER_ID FROM DUAL
	    )
	    LOOP
	    DBMS_OUTPUT.putline(ID_LIST.USER_ID);
	END LOOP;
	END;

 

※ CURSOR FOR LOOP은 내부적으로 처리되는 데이터의 양, I/O 측면에서 훨씬 효율적, 가급적 사용 권장

'Study > Oracle' 카테고리의 다른 글

PL/SQL_6 - 테이블 함수  (0) 2021.05.18
PL/SQL 기본_5 - 함수  (0) 2021.05.17
PL/SQL 기본_4 - 프로시저  (0) 2021.05.10
PL/SQL 기본_2 - 반복문과 제어문  (0) 2021.05.10
PL/SQL 기본_1  (0) 2021.05.10

PL/SQL에서의 반복문은 크게 LOOP, FOR로 볼 수 있다.

 

FOR LOOP

  • 문법
FOR index in [REVERSE] 시작값 .. END값 LOOP
        STATEMENT 1
        STATEMENT 2
        ...
    END LOOP;
    
  • index는 자동 선언되는 binary_integer형 변수이고, 1씩 증가
  • REVERSE 옵션이 사용될 경우 index는 upper_bound에서 lower_bound로 1씩 감소
  • IN 다음에는 cursor나 SELECT 문이 올 수 있다.

 

  • EX 1)
SET serveroutput ON;
	BEGIN
		FOR i in 1..4 LOOP
	  		if mod(i, 2) = 0 then 
				dbms_output.put_line( i || '는 짝수!!');
			else
				dbms_output.put_line( i || '는 홀수!!');
			end if;
		END LOOP;
	END;

 

  • EX 2) 간단한 FOR문 안에 SELECT문이 오는 예제
SET serveroutput ON;
	BEGIN
		FOR NUM_LIST IN 
	    (
	        SELECT 1 AS NUM FROM DUAL
	        UNION ALL
	        SELECT 2 AS NUM FROM DUAL
	        UNION ALL
	        SELECT 3 AS NUM FROM DUAL
	        UNION ALL
	        SELECT 4 AS NUM FROM DUAL
	    )
	    LOOP
		  	if mod(NUM_LIST.NUM, 2) = 0 then 
				dbms_output.put_line( NUM_LIST.NUM || '는 짝수!!');
			else
				dbms_output.put_line( NUM_LIST.NUM || '는 홀수!!');
			end if;
		END LOOP;
	END;

 

LOOP

  • 문법
    LOOP 
        PL/SQL STATEMENT 1
           다른 LOOP를 포함하여 중첩으로 사용 가능
        EXIT [WHEN CONDITION]
    END LOOP;
  • EXIT 문이 사용되었을 경우, 무조건 LOOP문을 빠져나간다.
  • EXIT WHEN 조건이 사용될 경우, WHEN절에서 LOOP를 빠져나가는 조건을 제어할 수 있다.

 

  • EX 1) 기본 LOOP문 예제
	SET serveroutput ON;
	DECLARE
	    v_num NUMBER := 6; -- 시작숫자
	    v_tot_num NUMBER := 0; -- 총 loop수 반환 변수
	BEGIN
	    LOOP
	        DBMS_OUTPUT.PUT_LINE('현재 숫자 : ' || v_num);
	        v_num := v_num + 1;
	        v_tot_num := v_tot_num + 1;
	        EXIT WHEN v_num > 10;
	    END LOOP;
	    
	    DBMS_OUTPUT.PUT_LINE(v_tot_num || '번의 LOOP');
	END;

 

  • EX 2) WHILE LOOP문 예제
	SET serveroutput ON;
	DECLARE
	    v_num NUMBER := 6; -- 시작숫자
	    v_tot_num NUMBER := 0; -- 총 loop수 반환 변수
	BEGIN
	    WHILE v_num < 11 LOOP
	        DBMS_OUTPUT.PUT_LINE('현재 숫자 : ' || v_num);
	        v_num := v_num + 1;
	        v_tot_num := v_tot_num + 1;
	        -- EXIT WHEN v_num > 10;
	    END LOOP;
	    DBMS_OUTPUT.PUT_LINE(v_tot_num || '번의 LOOP');
	END;

 

 

제어문

IF문, CASE문 등의 제어문을 PL/SQL에서도 사용할 수 있다.

 

IF

  • 문법
    IF 조건1 THEN
        처리문1
    ELSE IF 조건2 THEN
        처리문2
        ...
    ELSE
        처리문
    END IF;
  • IF문은 조건값이 참이면 해당 조건의 처리 문장이 실행
  • 다른 프로그래밍 IF문과 다른 점
    • 조건 다음에 THEN을 붙인다.
    • 보통 ELSE IF를 쓰지만, PL/SQL에서는 ELSIF 명령어를 사용한다.
    • 마지막에는 IF를 끝낸다는 END IF를 붙인다.
  • EX 1) 기본 IF문 예제
	DECLARE
	    v_score NUMBER := 79;
	BEGIN
	  IF v_score >= 90 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : A');
	  ELSIF v_score >= 80 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : B');
	  ELSIF v_score >= 70 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : C');
	  ELSIF v_score >= 60 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : D');
	  ELSE
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : F');
	  END IF;
	END;

 

  • EX 2) IF문 예제 2 - 조건이 NULL인 경우
    • NULL의 비교는 항상 NULL이기 때문에, ELSE 이하 문만 수행
	DECLARE
	    v_score NUMBER;
	BEGIN
	  IF v_score >= 90 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : A');
	  ELSIF v_score >= 80 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : B');
	  ELSIF v_score >= 70 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : C');
	  ELSIF v_score >= 60 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : D');
	  ELSE
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : F');
	  END IF;
	END;

 

CASE문

  • 문법
    • 오라클 CASE문과 유사
	CASE WHEN 조건1 THEN
	    처리문1
	WHEN 조건2 THEN
	    처리문2
	    ...
	ELSE
	    처리문
	END CASE;

 

  • EX 1) CASE 표현식 예제
    • 단순하게 조건문에 따른 값을 대입할 때 사용
	DECLARE
	    v_grade     CHAR(1) := 'C';
	    v_appraisal VARCHAR2(20) ;
	BEGIN
	  v_appraisal := CASE v_grade
	  				WHEN 'A' THEN 'Excellent'
	  				WHEN 'B' THEN 'Very Good'
					WHEN 'C' THEN 'Good'
					ELSE 'No such grade'
	  			END;
	  DBMS_OUTPUT.PUT_LINE ('Grade : '|| v_grade) ;
	  DBMS_OUTPUT.PUT_LINE ('Appraisal: '|| v_appraisal);
	END;

 

  • EX 2) CASE 조건문 예제
    • 단순한 값이 아닌 PL/SQL문(명령문)을 실행하고자 하는 경우에 CASE 조건문 사용
    • CASE 조건문은 끝이 END CASE로 끝남
	DECLARE
	    v_grade     CHAR(1) := 'C';
	    v_appraisal VARCHAR2(20) ;
	BEGIN
	  CASE v_grade
	  WHEN 'A' THEN
	  	v_appraisal := 'Excellent';
	  WHEN 'B' THEN
	    v_appraisal := 'Very Good';
	  WHEN 'C' THEN
	    v_appraisal := 'Good';
	  ELSE
	    v_appraisal := 'No such grade';
	  END CASE;
	  DBMS_OUTPUT.PUT_LINE ('Grade : '|| v_grade) ;
	  DBMS_OUTPUT.PUT_LINE ('Appraisal: '|| v_appraisal);
	END;

'Study > Oracle' 카테고리의 다른 글

PL/SQL_6 - 테이블 함수  (0) 2021.05.18
PL/SQL 기본_5 - 함수  (0) 2021.05.17
PL/SQL 기본_4 - 프로시저  (0) 2021.05.10
PL/SQL 기본_3 - 커서  (0) 2021.05.10
PL/SQL 기본_1  (0) 2021.05.10

프로시저 작성을 위해 PL/SQL을 사용하게 되면서 갓대희님의 블로그를 참고하며 공부를 했다.

 

공부한 내용을 까먹지 않기 위해 블로그에 정리해보고자 한다.

 

우선 PL/SQL의 기본적인 정의를 정리해보자.

 

PL/SQL

  • SQL을 확장한 절차적 언어(Procedural Language)
  • Oracle의 표준 데이터 엑세스 언어로, 프로시저 생성자를 SQL과 완벽하게 통합
  • 유저 프로세스가 PL/SQL 블록을 보내면, 서버 프로세서는 PL/SQL Engine에서 해당 블록을 받고 SQL과 Procedural를 나눠서 SQL은 SQL Statement Executer로 보냄
  • PL/SQL 프로그램의 종료는 크게 Procedure, Function, Trigger로 나뉨
  • SQL에서는 사용할 수 없는 절차적 프로그래밍의 기능을 가지고 있어 SQL의 단점 보완

위와 같은 정의를 가지는 PL/SQL의 기본적인 특징도 정리해보자.

 

PL/SQL의 기본 특징

  • 블록 단위 실행 제공
    • 이를 위해 BEGIN, END; 사용
    • 마지막 라인에 /를 입력하면 해당 블록 실행
  • 변수, 상수 등을 선언하여 SQL과 절차형 언어에서 사용
  • 변수의 선언은 DECLARE 절에서만 가능
  • BEGIN 섹션에서 새 값 할당 가능
  • IF문을 통해 조건에 따라 문장들 분기 가능
  • LOOP문을 사용하여 문장 반복가능
  • 커서를 사용하여 여러 행 검색 및 처리
  • PL/SQL에서 사용 가능한 SQL은 Query, DML, TCL
    • DDL(CREATE, DROP, ALTER, TRUNCATE…), DCL(GRANT, REVOKE) 명령어는 동적 SQL을 이용할 때만 사용 가능
  • PL/SQL의 SELECT 문은 결과를 PL/SQL Engine으로 보냄
    • 이를 캐치하기 위한 변수를 DECLARE해야 하고, SELECT 문장은 반드시 한 개의 행이 검색되어야 함
    • 그리고 이를 위해 INTO 절을 꼭 사용해야 함
    • 검색되는 행이 없으면 문제 발생

 

PL/SQL Block의 기본 구조

영역 설명 필수 여부
DECLARE
(선언부)
PL/SQL에서 사용하는 모든 변수나 상수를 선언하는 부분

DECLARE로 시작
옵션
BEGIN
(실행부)
절차적 형식으로 SQL문을 실행할 수 있도록 절차적 언어의 요소인 제어문, 반복문, 함수 정의 등 로직을 기술할 수 있는 부분

BEGIN으로 시작
필수
EXCEPTION
(예외 처리부)
PL/SQL문이 실행되는 중에 에러가 발생할 수 있는데 이를 예외 사항이라고 함

이러한 예외 사항이 발생했을 때 이를 해결하기 위한 문장을 기술하는 부분
옵션
END
(실행문 종료)
  필수

 

PL/SQL Block의 종류

  • 익명 블록 : 이름이 없는 PL/SQL Block
  • 이름 있는 블록 : DB의 객체로 저장되는 블록
    • 프로시저 : 리턴 값을 하나 이상 가질 수 있는 프로그램
    • 함수 : 리턴 값을 반드시 반환해야 하는 프로그램
    • 패키지 : 하나 이상의 프로시저, 함수, 변수, 예외 등의 묶음
    • 트리거 : 지정된 이벤트가 발생하면 자동으로 실행되는 PL/SQL 블록

PL/SQL 프로그램 작성 요령

  • PL/SQL 블록 내에서 한 문장이 종료될 때마다 세미콜론(;)을 사용하여 한 문장의 끝을 명시
  • END 뒤에 세미콜론(;)을 사용하여 하나의 블록의 끝을 명시
  • 단일 행 주석은 --, 여러 행 주석은 /* */
  • 쿼리문을 실행하기 위해 '/'가 필수, PL/SQL 블록은 행에 '/'가 있으면 종결된 것으로 간주

[참고] 오라클에서 화면 출력을 위해서 PUT_LINE 프로시저 사용

  • DBMS_OUTPUT.PUT_LINE(출력할 내용)
  • 위 프로시저를 사용하여 출력되는 내용을 화면에 보여주기 위해서 환경 변수 SERVEROUTPUT ON(기본 값이 OFF)으로 변경

 

  • 메시지 출력하기 예시
SET serveroutput ON
BEGIN
	dbms_output.put_line('출력 예시');
END;

결과 - 출력 예시

 

변수 선언

  • 블록 내에서 변수를 사용하려면 선언부(DECLARE)에서 선언해야 하며 변수명 다음에는 데이터 타입을 기술
  • 문법
    • identifier [CONSTANT] datatype [NOT NULL]
      [:=|DEFAULT expression];
identifier 변수명(식별자)
CONSTANT 상수로 지정(초기값 반드시 할당)
datatype 자료형 기술
NOT NULL 값을 반드시 포함
expression Literal, 다른 변수, 연산자나 함수를 포함하는 표현식

 

문법으로만 보면 이해가 어렵기 때문에 예시를 통해 이해를 해보자

 

예시)

  • DECALRE 변수이름 데이터타입;
DECLARE NAME VARCHAR2(10);

 

  • DECLARE 변수이름 데이터타입 := 값;
DECLARE NAME VARCHAR2(10) := 'Pdache';

 

  • DECLARE 변수이름 데이터타입 DEFAULT 기본값;
DECLARE NAME VARCHAR2(10) DEFAULT 'PDH';

 

  • 한 번에 여러 개의 변수 선언
DECLARE 
	NAME	VARCHAR2(20);
	AGE		NUMBER(2); 
	GENDER	VARCHAR(50)	DEFAULT '남';

 

  • 변수 선언하고 사용
DECLARE NAME VARCHAR2(20) := '이효리';
	BEGIN
		DBMS_OUTPUT.put_Line('이효리'|| NAME); -- 출력
	END;

 

  • 변수 Type을 선언할 때 명시적으로 작성하지 않고 사용하는 방법
    • %ROWTYPE
      • 해당 테이블이나 뷰의 컬럼 속성을 그대로 들고 오는 형태
      • 사용 방법 : 변수명 테이블이름%ROWTYPE
    • %TYPE
      • 해당 테이블의 컬럼 속성을 지정하여 그대로 들고 오는 형태
      • 사용 방법 : 변수명 테이블이름.컬럼명%TYPE
  • %ROWTYPE 예시
DECLARE 
	DATA EMP%ROWTYPE;
BEGIN
	SELECT 	* INTO DATA 
	FROM 	EMP 
	WHERE 	EMPNO = '1234';
	DBMS_OUTPUT.PUT_LINE(DATA.ENAME ||','||DATA.DEPTNO);
END;

 

  • %TYPE 예시
DECLARE 
	V_ENAME  EMP.ENAME%TYPE;
	V_DEPTNO EMP.DEPTNO%TYPE;
BEGIN
	SELECT 	ENAME, DEPTNO INTO V_ENAME, V_DEPTNO
	FROM 	EMP 
	WHERE 	EMPNO = '1234';
	DBMS_OUTPUT.PUT_LINE(V_ENAME ||','||V_DEPTNO);
END;

 

변수 대입 방법

  • 명시적 값 대입
    • 변수 값을 저장하기 위해 := 사용
    • := 좌측에는 변수, 우측에는 값
  • SELECT 문을 이용한 값 대입
    • 기존 SELECT 문과는 다르게 INTO 추가
    • INTO 절에는 조회 결과 값을 저장할 변수 기술
    • SELECT 문은 INTO 절에 의해 하나의 행만을 저장
    • SELECT 다음에 기술한 컬럼은 INTO 절에 있는 변수와 1:1로 대응해야 하기 때문에 개수와 데이터 타입, 길이를 일치시켜야 한다.

'Study > Oracle' 카테고리의 다른 글

PL/SQL_6 - 테이블 함수  (0) 2021.05.18
PL/SQL 기본_5 - 함수  (0) 2021.05.17
PL/SQL 기본_4 - 프로시저  (0) 2021.05.10
PL/SQL 기본_3 - 커서  (0) 2021.05.10
PL/SQL 기본_2 - 반복문과 제어문  (0) 2021.05.10

+ Recent posts