절차형 프로그래밍 언어인 C언어처럼 SQL에도 절차 지향적인 프로그래밍이 가능하도록 벤더별로 프로그래밍 언어와 같은 절차형 SQL을 제공합니다.
오라클에서는 PL(Procedural Language)/SQL을 제공하며 SQL Server에서는 T-SQL 을 제공합니다.
이 포스팅은 오라클의 PL/SQL을 아주 간단하게 설명합니다.
PL/SQL은 기본적으로 BLOCK 구조로 되어있다. BLOCK 안에는 기본적으로 DECLARE, BEGIN, EXCEPTION으로 구성되어 있으며 마지막에는 END로 BLOCK의 끝을 표현합니다.
DECLARE: 선언부라고 하며 BEGIN ~ END 사이에서 사용할 변수에 대하여 정의하는 부분입니다. 정의할 게 없다면 생략도 가능합니다.
DECLARE
V_PI CONSTANT NUMBER := 3.14; -- 상수로 선언하였으며 변경 불가능하다.
v_name VARCHAR2(100) := '홍길동'; -- 변수로 선언하였으며 디폴트 값으로 미리 '홍길동'을 할당
v_addr VARCHAR2(100); -- 변수로 선언하였으며 디폴트 값을 선언하지 않았다.
v_you VHARCHAR2(100) := '&your_name'; -- 해당 블록을 실행할때마다 사용자한테 입력받는다.
v_deptId DEPT.DEPT_ID%TYPE -- DEPT 테이블의 DEPT_ID 컬럼의 데이터타입을 참조한다.
v_temp DEPT%ROWTYPE -- DEPT 테이블의 선언된 컬럼의 모든 데이터타입 아무거나 들어갈 수 있다.
BEGIN: 실행 부라고 하며 처리하고자 하는 SQL문과 필요한 로직을 기술하는 부분이다.
EXCEPTION: 예외처리 부라고 하며 실행 도중에 에러가 발생할 경우 에러를 처리하는 로직을 기술하는 부분이다. 생략 가능하다.
EXCEPTION
WHEN 예외명1 THEN
예외처리문장;
WHEN 예외명2 OR 예외명3 THEN
예외처리문장;
WHEN OTHERS THEN
나머지_예외처리문장;
DECLARE, BEGIN, EXCEPTION, END와 같은 예약어는 마지막에 세미콜론(;)을 붙이지 않습니다. 이외의 명령어는 세미콜론(;)을 붙입니다.
BLOCK안에 새로운 BLOCK을 포함할 수 있다. 이를 Nested Block이라고 표현합니다.
IF, LOOP 등의 조건을 사용하여 절차적인 프로그래밍이 가능합니다.
여러 SQL 문장을 Block으로 묶고 한 번에 Block 전부를 서버로 보내기 때문에 통신량을 줄일 수 있습니다.
PL/SQL로 작성된 코드는 PL/SQL 엔진이 처리하고, 일반적인 SQL 문장은 SQL 실행기가 처리합니다.
PL/SQL에서는 DML 문장은 직접적으로 쿼리를 작성하여 사용할 수 있습니다. 하지만 DDL, DCL, TCL은 직접적으로 지원하지 않습니다. 동적 SQL(런타임에 문자열로 작성되는 SQL)을 사용하면 가능하긴 합니다. 동적 SQL은 execute immediate를 이용합니다.
BEGIN
execute immediate 'TRUNCATE TABLE 사원';
END
PL/SQL을 저장해서 쉽게 사용할 수 있습니다. 저장하여 사용할 경우 Stored PL/SQL Block이라고 합니다. 저장하지 않고 사용할 경우에는 Anonymous PL/SQL Block이라고 합니다.
DECLARE
v_name VARCHAR2(10);
BEGIN
SELECT 사원명 INTO v_name FROM 사원 WHERE 사원ID = '1';
END
DECLARE
v_id VARCHAR2(4) := '&id';
v_name VARCHAR2(10) := '&name';
BEGIN
INSERT INTO 사원 VALUES(v_id, v_name);
END
IF 조건문
IF (조건) THEN
실행문장;
ELSE
실행문장;
END IF;
IF (조건) THEN
실행문장;
ELSEIF (조건) THEN
실행문장;
END IF;
CASE 조건문
CASE 변수
WHEN 조건1 THEN 결과1
WHEN 조건1 THEN 결과1
...
WHEN 조건N THEN 결과N
ELSE 디폴트결과
END;
LOOP 반복문
LOOP
문장;
EXIT 조건;
ENd LOOP;
WHILE 반복문
WHILE 조건 LOOP
문장;
END LOOP;
FOR 반복문
FOR 변수 IN 시작숫자..끝숫자 LOOP
문장;
END LOOP;
PL/SQL을 마치 함수처럼 정의해서 사용할 수 있습니다. 이를 Stored PL/SQL Block 이라고 합니다. 저장하지 않고 이름 없이 사용하는 것은 Anonymous PL/SQL Block 이라고 합니다. 아래는 두 개의 차이점을 정리한 내용입니다.
Stored PL/SQL Block | Anonymous PL/SQL Block |
---|---|
한 번 컴파일되어 데이터베이스에 저장됨 | 사용시마다 컴파일되고, 데이터베이스에 저장하지 않음 |
파라미터와 리턴값이 존재 | 파라미터와 리턴값이 존재하지 않음 |
다른 프로그램에서 호출 가능 | 다른 프로그램에서 호출 불가능 |
Stored PL/Block의 종류는 Procedure, Function, Package, Trigger 가 있습니다.
Procedure
CREATE PROCEDURE p_test -- 프로시저 명칭을 입력한다.
(
파라미터1 IN 데이터타입,
리턴값1 OUT 데이터타입,
둘다가능 IN OUT 데이터타입
)
IS
변수1 데이터타입;
PL/SQL Block
EXEC p_test() -- 인자가 없는 Procedure일 경우
EXEC p_test(파라미터1, 리턴값1, 둘다가능) -- 인자가 있는 Procedure일 경우
FUNCTION
CREATE FUNCTION f_test -- 함수 명칭을 입력한다.
(
파라미터1 IN 데이터타입,
리턴값1 OUT 데이터타입,
둘다가능 IN OUT 데이터타입
)
RETURN 데이터타입
IS
변수1 데이터타입;
PL/SQL Block
Package
-- 선언부
CREATE PACKAGE pack_test
IS
상수명 CONSTANT 데이터타입;
예외명 EXCEPTION;
변수명 데이터타입;
PROCEDURE 프로시저명칭 (변수타입들..);
FUNCTION 함수명칭 (변수타입들..) RETURN 반환타입;
END pack_test;
-- 바디부
CREATE PACKAGE BODY pack_test
IS
상수명 CONSTANT 데이터타입;
예외명 EXCEPTION;
변수명 데이터타입;
PROCEDURE 프로시저명칭 -- 프로시저 생성구문
...
END 프로시저명칭;
FUNCTION 함수명칭 -- 함수 생성구문
...
END 함수명칭;
END pack_test;
Trigger
CREATE [OR REPLACE] TRIGGER trigger_name
BEFORE | AFTER
trigger_event ON table_name
[FOR EACH ROW]
[WHEN (condition)]
PL/SQL block
CREATE TRIGGER 인서트제약트리거
BEFORE UPDATE ON 사원연봉
BEGIN
IF (:NEW.입력자) NOT IN ('대표') THEN
RAISE_APPLICATION_ERROR(-9999,'대표만 수정할 수 있습니다.');
END IF;
END