17. pl/sql - 경영정보학과mis.mju.ac.kr/~shpark/2010fall/advdb/pl_… · ppt file · web...
Post on 19-Mar-2018
230 Views
Preview:
TRANSCRIPT
PL/SQL
2
개 요 PL/SQL 의 필요성 및 특징
SQL 의 특징 4 세대 언어 간단하고 적은 수의 명령어를 가짐 사용자들에게 알고리즘을 은닉함
C 나 COBOL 등의 특징 3 세대 언어 절차적인 알고리즘으로 구현
위와 같은 각각의 언어들의 특징들을 사용하기 위하여 사용하게 된다 . 즉 3 세대 언어에서 가능한 절차적 구성이 4 세대 언어에서 필요할 때가 있는데 , 이런 경우를 위하여 PL/SQL이라는 언어가 도입
Oracle 에서의 PL/SQL 은 절차적프로그래밍을 할 수 있도록 SQL 을 확장
3
PL/SQL 의 기초 문자집합
대문자 A – Z, 소문자 a – z 숫자 0 – 9 기호 ( ) + - * / < > = ! ~ ^ ; : . @ % , “ # $ & _ | { } [ ] ? 탭 , 스페이스 , 캐리지 리턴
식별자 상수 , 변수 , 예외 사항 , 커서 , 서브 프로그램 등을 포함하는 PL/SQL
프로그램 아이템과 유닛들의 이름 문자로 시작하고 , 숫자 , 달러 기호 ($), 언더스코어 (_), 숫자기호 (#)
등을 조합하여 사용 예제
money$$$tree, SN#, try_again ( 허용됨 ) mine&yours, debit-amout, on/off, user id( 허용되지 않음 ) lastname, LastName, LASTNAME( 같은 것으로 간주 )
4
PL/SQL 의 기초 키워드
키워드 (keyword) 라고 불리는 식별자들은 PL/SQL 에서 특별한 의미를 가지고 있기 때문에 , 상수와 변수 또는 커서 등에 대한 이름으로 사용할 수 없음 ( 통상적으로 키워드는 가독성을 위하여 대문자로 사용 )
예제 DECLARE begin number ( 키워드 begin 을 사용하므로 에러 )
주석한 줄 주석을 사용
두줄 주석을 사용
5
-- 처리의 시작
SELECT sal INTO salary FROM emp
WHERE empno = emp_id; -- 현재 월급을 가져옴
bonus := salary * 0.15 – 보너스의 계산
/* 등급이 우수한 직원들에게 15% 의 보너스를 두고 , 그 외에는 보너스를 주지 않음 */
IF rating > 90 THEN
bonus := salary * 0.15 /* 월급에 기본을 두고 보너스 계산 */
ELSE
bonus := 0;
END IF;
6
PL/SQL 의 기초 데이타 타입
숫자타입BINARY_INTEGER : -2,147,483,647 ~
2,147,483,647 사이의 정수– SUBTYPE
» NATURAL : 음수를 제외한 정수 (0 ~ 2,147,483,647)» POSITIVE : 양의 정수 (1 ~ 2,147,483,647)» SIGNTYPE : -1, 0 , 1 의 값만 가짐
7
NUMBER : 10-130 ~ 10125 사이의 고정소수점이나 부동소수점 수– SUBTYPE
» DEC, DECIMAL, NUMERIC : 최대 38 자리의 고정 소수점 수» DOUBLE PRECISION, FLOAT: 최대 126 자리 이진부동소수점 수» REAL : 최대 63 자리 이진 부동 소수점 수» INTEGER, INT, SMALLINT : 최대 38 자리의 정수
PLS_INTEGER : -231 ~ 231 사이의 정수
8
PL/SQL 의 기초 데이타 타입
문자타입CHAR : 고정 길이의 문자열을 저장 . 32,767 바이트까지
저장가능– 사용예 : CHAR[( 길이 )]
VARCHAR2: 가변길이문자열을 저장 . 32,767 바이트까지 저장가능
– 사용예 : VARCHAR2( 최대길이 )LONG, LONG RAW : 가변길이 문자열을 저장 .RAW : 이진 데이타나 이진 문자열을 저장하기 위해 사용
– 사용예 : RAW( 최대크기 )
9
기타타입BOOLEAN : 논리적인 참 , 거짓 , 널값을 저장하기 위해
사용 . 오직 논리 연산만 허용 .DATE : 날짜와 시간을 저장하기 위해 DATE 타입을 사용 .
DATE 타입의 값은 자정 이후의 시간을 초 단위도 포함하여 저장 .
10
PL/SQL 의 구조 PL/SQL
블록 구조의 언어삽입 SQL 문을 지원프로시저와 함수의 선언조건 , 반복 과 같은 제어문 변수 선언
PL/SQL 블록선언부 ( 생략가능 )실행부 ( 필수 )예외 상황 처리부 ( 생략가능 )
11
선언부
실행부
예외 상황 처리부
Declare
Begin
Exception
End;
생략가능
생략가능
필수
12
선언부 변수선언
한줄에 하나의 변수만 선언 가능
DECLARE v_job VARCHAR2(9); v_count BINARY_INTEGER := 0; v_total_sal NUMBER(9,2) := 0; v_hiredate DATE; v_valid BOOLEAN := FALSE; BEGIN
13
DEFAULT 의 사용:= 연산자 대신에 키워드 DEFAULT 를 사용하여 변수에 초기값을 할당
DECLARE blood_type CHAR := ‘O’; -- blood_type CHAR DEFAULT ‘O’BEGIN
14
선언부 변수선언
NOT NULL 의 사용 : 초기값을 할당하는 것 이외에 , NOT NULL 제약을 변수에 부여
%TYPE 속성의 사용 v_student_name 은 이미 선언된 변수 v_name 과 동일한 VARCHA
R2(10) 으로 선언
DECLARE v_emp_id NUMBER(4) NOT NULL := 9999; -- 적합 v_dept_no NUMBER(2) NOT NULL; -- 에러BEGIN
DECLARE v_name VARCHAR2(10); v_student_name v_name%TYPE; v_st_name v_name%TYPE := ‘scott’BEGIN
15
선언부 변수선언
%ROWTYPE 속성의 사용Student 테이블이 두 애트리뷰트 name, grade 를 포함하고
있을 때 , 아래 선언의 결과로 v_student_rec 와 v_stu_rec변수는 student 테이블의 레코드와 동일한 복합 변수로 선언
다음과 같은 SELECT 명령에서의 v_stu_rec 와 같이 %ROWTYPE 속성은 SELECT 명령에서 행을 가져 올 때 매우 유용
16
DECLARE v_student_rec student%ROWTYPE; v_stu_rec student%ROWTYPE; BEGIN v_student_rec.name := ‘JOHNSON’; v_student_rec.grade := ‘A’; ⋮ SELECT * INTO v_stu_rec FROM student WHERE ... ⋮END;
17
선언부 상수선언
키워드 CONSTANT 를 명시하고 반드시 기본값을 지정DECLARE c_num CONSTANT NUMBER := 100;BEGIN c_num := 200; -- 에러END;
18
선언부커서 선언
커서 : SQL 명령을 실행할 때 , 오라클 서버는 명령이 파싱 되고 , 실행되는 메모리의 영역을 오픈하는데 이 영역을 커서 (Cursor) 라고 함 .
하나의 행만 반환하는 질의를 포함한 모든 데이타 조작 SQL 명령에 대해서는 묵시적으로 커서를 선언하고 , 하나 이상의 행을 반환하는 SELECT 명령에 대해서는 사용자가 명시적으로 커서를 선언
19
구 분 묵시적 커서 명시적 커서생성 및 관리 DBMS 사용자선 언 SELECT, DML 문에 의해 DECLARE
CURSOR C1 IS SELECT 명령 ;BEGIN
속 성 %NotFound%Found%ISOpen( 항상 False)%RowCount
%NotFound%Found%ISOpen%RowCount
20
선언부 커서선언
예제c1, c2 라는 이름의 두개의 커서를 선언c1 은 emp 테이블에서 월급이 2000 보다 많은 직원들의
사원번호와 이름 , 직업 , 웕급을 가져오는 커서c2 는 dept 테이블에서 부서번호가 10 번인 부서의 레코드를
가져 오는 커서이고 반환 타입은 dept 테이블에 속한 모든 열들을 가져오도록 %ROWTYPE 속성을 이용
21
DECLARE CURSOR c1 IS SELECT empno, ename, job, sal FROM emp; WHERE sal > 2000; CURSOR c2 RETURN dept%ROWTYPE IS SELECT * FROM dept WHERE deptno = 10; BEGIN
22
실행부 SQL 명령
SELECT 명령에서 INTO 절을 사용하여 SELECT 명령에 의해 반환되는 결과를 PL/SQL 의 변수에 저장가능아래의 예제는 s_dept 테이블에서 id 가 10 인 부서이름
name 을 검색하여 그 값을 v_name 에 지정DECLARE v_name s_dept.name%TYPE;BEGIN SELECT name INTO v_name FROM s_dept WHERE id = 10; ⋮END;
23
실행부 SQL 명령
INSERT, UPDATE, DELETE SQL 명령으로 데이타를 삽입 , 갱신 , 삭제 가능BEGIN INSERT INTO emp(empno, ename) VAULES(8288, ‘TEST’); ⋮ UPDATE dept SET dname = ‘EDUCATION’ WHERE deptno = 10; ⋮ DELETE FROM emp WHERE deptno = 20; ⋮END;
24
실행부 IF 문
IF – THEN
IF – THEN – ELSE
IF 조건 THEN
문 ;
END IF;
IF 조건 THEN
문 1;
ELSE
문 2;
END IF;
25
IF – THEN – ELSIF
IF 조건 1 THEN
문 1;
ELSEIF 조건 2 THEN
문 2;
[ELSEIF 조건 3 THEN
문 3;]
…
[ELSE
문 4;]
END IF;
26
실행부 반복 실행문
반복실행문은 명령들을 여러 번 반복해서 수행 반복 실행문 : LOOP, WHILE, FOR 문
LOOP
27
LOOP
…
EXIT WHEN 조건 ;
END LOOP;
28
실행부 반복 실행문
WHILE 루프WHILE 조건 LOOP
…
END LOOP;
29
실행부 반복 실행문
FOR 루프FOR 루프변수 IN [REVERSE] 하한 .. 상한 LOOP
…
END LOOP;
30
실행부 GOTO 문
PL/SQL 에서는 GOTO 문을 이용하여 무조건 분기실행할 때 GOTO 문은 제어를 레이블이 있는 위치로 이동GOTO 레이블 ;
…
<< 레이블 >>
BEGIN
…
GOTO insert_row;
…
<<insert_row>>
INSERT INTO emp VALUES …
END;
31
실행부 NULL 문
NULL 문은 아무 일도 하지 않는다는 사실을 명시적으로 나타냄IF rating > 90 THEN
compute_bonus(emp_id);
ELSE
NULL;
END IF;
32
실행부 커서의 조작
커서는 OPEN, FETCH, CLOSE 문을 이용하여 제어OPEN 문은 커서와 관련된 질의를 실행하고 , 커서가 반환 한 값 중에서 첫 번째 행을 지시FETCH 문은 현재 행을 읽어 들인 후 , 다음 행으로 커서를 이동시킴커서를 종료할 때는 CLOSE 문을 사용커서의 오픈DECLARE
CURSOR c1 IS SELECT empno, ename, job, sal FROM emp WHERE sal > 2000; ...BEGIN OPEN c1; ... END;
33
실행부 커서의 조작
데이타의 FETCHFETCH 명령은 결과 집합에서 한 번에 한 행만을 가져옴한 번의 FETCH 후에 커서는 결과 집합에서 다음 행을 지시 FETCH c1 INTO my_empno, my_ename, my_deptno;
BEGIN
LOOP
FETCH c1 INTO my_record;
EXIT WHEN c1%NOTFOUND;
… -- 데이타 레코드의 처리END LOOP
…
END;
34
실행부 커서의 조작
데이타의 FETCHFOR LOOP 을 이용한 예제
35
실행부 커서의 조작
CLOSE 명령은 커서를 비활성화 결과 집합이 정의 되지 않은 상태로 만듬 종료된 커서에 대한 연산은 미리 정의된 예외인 INVALID_CURSOR 를
발생
DECLARE
CURSOR c1 IS -- 커서의 선언SELECT …
BEGIN
OPEN c1; -- 커서 오픈…
FETCH c1 INTO …; -- 데이타의 FETCH
…
CLOSE c1; -- 커서 종료END;
36
실행부 커서의 조작
명시적 커서의 속성 %FOUND
– 커서를 오픈했을 때 첫번째 FETCH 가 실행되기 전에 %FOUND 는 NULL 값
BEGIN
…
LOOP
FETCH c1 INTO my_ename, my_sal, my_hiredate;
IF c1%FOUND THEN -- FETCH 의 성공
… -- 데이타의 처리
ELSE
EXIT;
END IF;
END LOOP;
…
END;
37
실행부 커서의 조작
%ISOPEN– %ISOPEN 은 커서가 오픈되었으면 참 , 그렇지 않으면 거짓BEGIN
…
IF c1%ISOPEN THEN -- 커서가 오픈된 상태
…
ELSE
OPEN c1;
END IF
…
END;
38
실행부 커서의 조작
%NOTFOUND– %NOTFOUND 는 %FOUND 와 논리적으로 반대 의미– 가장 최근에 FETCH 가 행을 반환하면 %NOTFOUND 는 거짓– 가장 최근의 FETCH 가 행을 반환하는데 실패하면 참BEGIN
LOOP
FETCH c1 INTO my_ename, my_sal, my_hiredate;
EXIT WHEN c1%NOTFOUND;
…
END LOOP;
…
END;
39
실행부 커서의 조작
%ROWCOUNT– 커서를 오픈했을 때 , %ROWCOUNT 는 0– 첫번째 FETCH 이전에는 %ROWCOUNT 는 0– %ROWCOUNT 는 계 속 가져온 행들의 수를 기록– FETCH 가 행을 가져오는데 성공할 때마다 , %ROWCOUNT 의 값은 하나씩 증가
BEGIN
…
LOOP
FETCH c1 INTO my_ename, my_sal, my_hiredate;
IF c1%ROWCOUNT > 10 THEN
… -- 데이타의 처리
END IF;
…
END LOOP;
…
END;
40
예외 상황 처리부 예외 상황 사용의 장점
에러 처리 루틴을 분리함으로써 가독성을 향상시킴안정성을 향상 시킴BEGIN
SELECT ...SELECT ...SELECT ......
EXCEPTIONWHEN NO_DATA_FOUND THEN
-- 모든 ‘ no data found’ 에러를 처리
41
예외 상황 처리부 미리 정의된 예외 상황예외 상황 Orac
le Error
SQL CODE값
내 용
No_Data_Found
ORA-0140
3
+100 행이 한건도 반환되지 않음
Too_Many_Rows
ORA-0142
2
-1422 행이 두개 이상 반환
Zero_Divide ORA-0147
6
-1476 제수가 0 일 때
Invalid_Number
ORA-0172
2
-1722 숫자 형태가 아닌 값을 숫자변수에 대입할 때Login_Denied
ORA-0101
7
-1017 잘못된 userid/password 로 접속을 시도 했을 때
Not_Logged_On
ORA-0101
2
-1012 오라클에 접속하지 않고 PL/SQL 을 수행했을 때
Others 위에서 명세되지 않은 예외 상황
42
예외 상황 처리부 사용자 정의 예외 상황
예외 상황의 선언
예외 상황의 명시적인 발생미리 정의된 예외 상황과는 달리 RAISE 명령에 의해 명시적으로 발생
DECLAREpast_due
EXCEPTION;
RAISE out_of_stock;
43
예외 상황 처리부 예외 상황 전파
에러 발생시 가장 가까운 예외 상황 처리부를 찾아 실행DECLARE temp NUMBER; v_salary NUMBER;BEGIN SELECT salary INTO v_salary FROM s_emp WHERE id = 1; DECLARE v_start_date DATE; v_date DATE; BEGIN SELECT start_date INTO v_date FROM s_emp WHERE id = 99; v_date := v_start_date + 15; EXCEPTION WHEN No_Data_Found THEN message(' 데이타 없음 '); END; temp := v_salary * 12;EXCEPTION WHEN Too_Many_Rows THEN message(' 중복 데이타 ');END;
44
예외 상황 처리부 예외 상황 전파
45
서브프로그램 프로시저
구조
저장 프로시저 : 재사용 가능
PROCEDURE 프로시저이름 [( 매개변수 1, ... [, 매개변수 n])] IS
[ 변수선언 ]BEGIN 실행부 ;[ 예외상황 처리부 ]END [ 프로시저이름 ];
CREATE [OR REPLACE] PROCEDURE 프로시저이름[( 매개변수 1, ... [, 매개변수 n])] IS
[ 변수선언 ]BEGIN 실행부 ;[ 예외상황 처리부 ]END [ 프로시저이름 ];
46
서브프로그램 프로시저raise_salary(7844, 1000); 1. emp_audit
테이블 생성
2. emp_audit테이블의
데이타 확인
47
서브프로그램 프로시저
raise_salary 프로시저를 포함한 PL/SQL 블록을 실행한 후 , emp 테이블에서 결과를 다시 확인
3. raise_salary프로시저 예제실행화면
48
서브프로그램 프로시저
raise_salary(8528, 100) - empno 가 8528 인 emp 행이 없기 때문에 emp_audit 테이블에 에러 메시지가 저장
4. emp 테이블의 데이타와
에러메시지 확인
49
서브프로그램 프로시저
프로시저를 오라클 데이타베이스에 저장하여 , 저장 프로시저로 만들면 영구적으로 재사용이 가능CREATE [OR REPLACE] 명령을 사용하여 프로시저를 저장 OR REPLACE 절은 동일한 이름의 프로시저가 이미 저장되어 있다면 그 프로시저의 내용을 지금 작성 하는 프로시저로 변경하라는 의미 CREATE [OR REPLACE] PROCEDURE 프로시저 이름
[( 인자 1, … [, 인자 n])] IS
[ 변수선언 ]
BEGIN
실행부 ;
[ 예외상황 처리부 ]
END [ 프로시저 이름 ];
50
서브프로그램 프로시저
앞의 예제
51
서브프로그램 프로시저
자신이 어떤 프로시저를 만들었는지 알고 싶다면 user_objects 데이타 딕셔너리에 질의
저장 프로시저의 인자에 대한 정보를 검색해 보고 싶으면 DESC 명령을 사용
52
서브프로그램 함수
프로시저와 유사프로시저와의 차이점 : 함수는 미리 정의된 데이타 타입의 값을 반환FUNCTION 함수이름 [( 인자 1, … [, 인자 n])]
RETURN 함수 _ 데이타 타입 IS
[ 변수선언 ]
BEGIN
실행부 ;
[ 예외 상황 처리부 ]
END [ 함수이름 ];
53
서브프로그램 함수
직업이 title 이고 봉급이 salary 일 때 , sals 테이블에 기록된 최소 봉급과 최대 봉급 범위에 salary 가 해당하는지 여부를 나타내는 예제
함수 이름 sal_ok 는 RETURN 명령에 의해 Boolean 값을 가짐FUNCTION sal_ok(salary REAL, title VARCHAR2)
RETURN BOOLEAN IS
min_sal REAL;
max_sal REAL;
BEGIN
SELECT low_sal, high_sal INTO min_sal, max_sal
FROM sals
WHERE job = title;
RETURN (salary >= min_sal) AND (salary <= max_sal);
END sal_ok;
54
서브프로그램 함수
1. sals 테이블생성
2. sals 테이블에데이타 입력
55
서브프로그램 함수
3. sal_ok 함수 예제의 실행
56
서브프로그램 함수
4. 저장함수sal_ok 의 생성
5. 저장함수에대한 정보 보기
57
서브프로그램 서브 프로그램의 인자
서브 프로그램에서 사용되는 인자들의 유형 IN( 디폴트 ) , OUT, IN OUT 함수의 인자 유형으로 OUT, IN OUT 을 사용 – 바람직하지 않음
IN IN 유형으로 정의된 인자의 특징
– 인자값을 함수나 프로시저에 전달할 뿐 , 값을 지정 하거나 값을 반환할 수 없음– 확인 예제
PROCEDURE debit_account (acct_id IN INTEGER, amount IN REAL) IS
minimum_purchase CONSTANT REAL := 10.0;
service_charge CONSTANT REAL := 0.50;
BEGIN
…
IF amount < minimum_purchase THEN
amount := amount + service_charge;
-- 컴파일 에러 발생END IF;
END;
58
서브프로그램 서브 프로그램의 인자
OUT값을 참조하지 않고 , 서브 프로그램을 호출한 PL/SQL 문에 값을 반환하는데 사용확인예제PROCEDURE calc_bonus (emp_id IN INTEGER, bonus OUT REAL) IS
hire_date DATE;
BEGIN
SELECT sal * 0.10, hiredate INTO bonus, hire_date
FROM emp
WHERE empno = emp_id;
IF MONTHS_BETWEEN(SYSDATE, hire_date) > 60 THEN
bonus := bonus + 500; -- 에러발생
END IF;
END;
59
서브프로그램 서브 프로그램의 인자
IN OUT 인자값을 서브프로그램에 전달하거나 호출 PL/SQL 문에 값을 반환시 사용
PROCEDURE calc_bonus (emp_id IN INTEGER, bonus IN OUT REAL) IS
hire_date DATE;
bonus_missing EXCEPTION;
BEGIN
SELECT sal * 0.10, hiredate INTO bonus, hire_date
FROM emp
WHERE empno = emp_id;
IF bonus IS NULL THEN
RAISE bonus_missing;
END IF;
IF MONTHS_BETWEEN(sysdate, hire_date) > 60 THEN
bonus := bonus + 500;
END IF;
EXCEPTION
WHEN bonus_missing THEN
END calc_bonus;
60
실행부 커서의 조작
커서는 OPEN, FETCH, CLOSE 문을 이용하여 제어OPEN 문은 커서와 관련된 질의를 실행하고 , 커서가 반환 한 값 중에서 첫 번째 행을 지시FETCH 문은 현재 행을 읽어 들인 후 , 다음 행으로 커서를 이동시킴커서를 종료할 때는 CLOSE 문을 사용커서의 오픈
61
DECLARE CURSOR c1 IS SELECT empno, ename, job, sal FROM emp WHERE sal > 2000; ...BEGIN OPEN c1; ... END;
62
실행부 커서의 조작
데이타의 FETCHFETCH 명령은 결과 집합에서 한 번에 한 행만을 가져옴한 번의 FETCH 후에 커서는 결과 집합에서 다음 행을 지시
63
FETCH c1 INTO my_empno, my_ename, my_deptno;
BEGIN
LOOP
FETCH c1 INTO my_record;
EXIT WHEN c1%NOTFOUND;
… -- 데이타 레코드의 처리END LOOP
…
END;
64
실행부 커서의 조작
데이타의 FETCHFOR LOOP 을 이용한 예제
65
66
실행부 커서의 조작
CLOSE 명령은 커서를 비활성화 결과 집합이 정의 되지 않은 상태로 만듬 종료된 커서에 대한 연산은 미리 정의된 예외인 INVALID_CURSOR 를
발생
67
DECLARE
CURSOR c1 IS -- 커서의 선언SELECT …
BEGIN
OPEN c1; -- 커서 오픈…
FETCH c1 INTO …; -- 데이타의 FETCH
…
CLOSE c1; -- 커서 종료END;
68
실행부커서의 조작
명시적 커서의 속성%FOUND
– 커서를 오픈했을 때 첫번째 FETCH 가 실행되기 전에 %FOUND 는 NULL 값
69
BEGIN
…
LOOP
FETCH c1 INTO my_ename, my_sal, my_hiredate;
IF c1%FOUND THEN -- FETCH 의 성공
… -- 데이타의 처리
ELSE
EXIT;
END IF;
END LOOP;
…
END;
70
실행부커서의 조작
%ISOPEN– %ISOPEN 은 커서가 오픈되었으면 참 , 그렇지
않으면 거짓
71
BEGIN
…
IF c1%ISOPEN THEN -- 커서가 오픈된 상태
…
ELSE
OPEN c1;
END IF
…
END;
72
실행부커서의 조작
%NOTFOUND– %NOTFOUND 는 %FOUND 와 논리적으로 반대 의미– 가장 최근에 FETCH 가 행을 반환하면 %NOTFOUND 는 거짓– 가장 최근의 FETCH 가 행을 반환하는데 실패하면 참
73
BEGIN
LOOP
FETCH c1 INTO my_ename, my_sal, my_hiredate;
EXIT WHEN c1%NOTFOUND;
…
END LOOP;
…
END;
74
실행부커서의 조작
%ROWCOUNT– 커서를 오픈했을 때 , %ROWCOUNT 는 0– 첫번째 FETCH 이전에는 %ROWCOUNT 는 0– %ROWCOUNT 는 계속 가져온 행들의 수를 기록– FETCH 가 행을 가져오는데 성공할 때마다 , %ROWCOUNT 의
값은 하나씩 증가
75
BEGIN
…
LOOP
FETCH c1 INTO my_ename, my_sal, my_hiredate;
IF c1%ROWCOUNT > 10 THEN
… -- 데이타의 처리
END IF;
…
END LOOP;
…
END;
76
예외 상황 처리부 예외 상황 사용의 장점
에러 처리 루틴을 분리함으로써 가독성을 향상시킴안정성을 향상 시킴
BEGINSELECT ...SELECT ...SELECT ......
EXCEPTIONWHEN NO_DATA_FOUND THEN
-- 모든 ‘ no data found’ 에러를 처리
77
예외 상황 처리부 미리 정의된 예외 상황
78
예외 상황 Oracle Error
SQL CODE 값 내 용
No_Data_Found
ORA-01403
+100 행이 한건도 반환되지 않음Too_Many_Rows
ORA-01422
-1422 행이 두개 이상 반환Zero_Divide ORA-
01476-1476 제수가 0 일 때
Invalid_Number
ORA-01722
-1722 숫자 형태가 아닌 값을 숫자변수에 대입할 때Login_Denied ORA-
01017-1017 잘못된 userid/password 로
접속을 시도 했을 때
Not_Logged_On
ORA-01012
-1012 오라클에 접속하지 않고 PL/SQL을 수행했을 때Others 위에서 명세되지 않은 예외
상황
79
예외 상황 처리부 사용자 정의 예외 상황
예외 상황의 선언
예외 상황의 명시적인 발생미리 정의된 예외 상황과는 달리 RAISE 명령에 의해 명시적으로 발생
DECLAREpast_due
EXCEPTION;
RAISE out_of_stock;
80
예외 상황 처리부 예외 상황 전파
에러 발생시 가장 가까운 예외 상황 처리부를 찾아 실행
81
DECLARE temp NUMBER; v_salary NUMBER;BEGIN SELECT salary INTO v_salary FROM s_emp WHERE id = 1; DECLARE v_start_date DATE; v_date DATE; BEGIN SELECT start_date INTO v_date FROM s_emp WHERE id = 99; v_date := v_start_date + 15; EXCEPTION WHEN No_Data_Found THEN message(' 데이타 없음 '); END; temp := v_salary * 12;EXCEPTION WHEN Too_Many_Rows THEN message(' 중복 데이타 ');END;
82
예외 상황 처리부 예외 상황 전파
83
84
서브프로그램 프로시저
구조PROCEDURE 프로시저이름 [( 매개변수 1, ... [, 매개변수n])] IS
[ 변수선언 ]BEGIN 실행부 ;[ 예외상황 처리부 ]END [ 프로시저이름 ];
85
CREATE [OR REPLACE] PROCEDURE 프로시저이름[( 매개변수 1, ... [, 매개변수 n])] IS
[ 변수선언 ]BEGIN 실행부 ;[ 예외상황 처리부 ]END [ 프로시저이름 ];
저장 프로시저 : 재사용 가능
86
서브프로그램 프로시저
raise_salary(7844, 1000);
1. emp_audit테이블 생성
87
2. emp_audit테이블의
데이타 확인
88
서브프로그램 프로시저
raise_salary 프로시저를 포함한 PL/SQL 블록을 실행한 후 , emp 테이블에서 결과를 다시 확인
89
3. raise_salary프로시저 예제실행화면
90
서브프로그램 프로시저
raise_salary(8528, 100) - empno 가 8528 인 emp 행이 없기 때문에 emp_audit 테이블에 에러 메시지가 저장
91
4. emp 테이블의 데이타와
에러메시지 확인
92
서브프로그램 프로시저
프로시저를 오라클 데이타베이스에 저장하여 , 저장 프로시저로 만들면 영구적으로 재사용이 가능CREATE [OR REPLACE] 명령을 사용하여 프로시저를 저장 OR REPLACE
동일한 이름의 프로시저가 이미 저장되어 있다면 그 프로시저의 내용을 지금 작성 하는 프로시저로 변경하라는 의미
93
CREATE [OR REPLACE] PROCEDURE 프로시저 이름[( 인자 1, … [, 인자 n])] IS
[ 변수선언 ]BEGIN
실행부 ;[ 예외상황 처리부 ]END [ 프로시저 이름 ];
94
서브프로그램 프로시저
앞의 예제
95
서브프로그램 프로시저
자신이 어떤 프로시저를 만들었는지 알고 싶다면 user_objects 데이타 딕셔너리에 질의
96
저장 프로시저의 인자에 대한 정보를 검색해 보고 싶으면 DESC 명령을 사용
97
서브프로그램 함수
프로시저와 유사프로시저와의 차이점 : 함수는 미리 정의된 데이타 타입의 값을 반환
FUNCTION 함수이름 [( 인자 1, … [, 인자 n])]RETURN 함수 _ 데이타 타입 IS
[ 변수선언 ]BEGIN
실행부 ;[ 예외 상황 처리부 ]END [ 함수이름 ];
98
서브프로그램함수
직업이 title 이고 봉급이 salary 일 때 , sals 테이블에 기록된 최소 봉급과 최대 봉급 범위에 salary 가 해당하는지 여부를 나타내는 예제
함수 이름 sal_ok 는 RETURN 명령에 의해 Boolean 값을 가짐
99
FUNCTION sal_ok(salary REAL, title VARCHAR2)
RETURN BOOLEAN IS
min_sal REAL;
max_sal REAL;
BEGIN
SELECT low_sal, high_sal INTO min_sal, max_sal
FROM sals
WHERE job = title;
RETURN (salary >= min_sal) AND (salary <= max_sal);
END sal_ok;
100
서브프로그램 함수 1. sals
테이블생성
101
2. sals 테이블에데이타 입력
102
서브프로그램 함수
3. sal_ok 함수 예제의 실행
103
서브프로그램 함수 4. 저장함수
sal_ok 의 생성
104
5. 저장함수에대한 정보 보기
105
서브프로그램서브 프로그램의 인자
서브 프로그램에서 사용되는 인자들의 유형 IN( 디폴트 ) , OUT, IN OUT 함수의 인자 유형으로 OUT, IN OUT 을 사용 – 바람직하지
않음IN
IN 유형으로 정의된 인자의 특징– 인자값을 함수나 프로시저에 전달할 뿐 , 값을 지정 하거나 값을
반환할 수 없음– 확인 예제
106
PROCEDURE debit_account (acct_id IN INTEGER, amount IN REAL) IS
minimum_purchase CONSTANT REAL := 10.0;service_charge CONSTANT REAL := 0.50;
BEGIN…IF amount < minimum_purchase THEN
amount := amount + service_charge;-- 컴파일 에러 발생
END IF;END;
107
서브프로그램서브 프로그램의 인자
OUT값을 참조하지 않고 , 서브 프로그램을 호출한
PL/SQL 문에 값을 반환하는데 사용확인예제
108
PROCEDURE calc_bonus (emp_id IN INTEGER, bonus OUT REAL) IS
hire_date DATE;
BEGIN
SELECT sal * 0.10, hiredate INTO bonus, hire_date
FROM emp
WHERE empno = emp_id;
IF MONTHS_BETWEEN(SYSDATE, hire_date) > 60 THEN
bonus := bonus + 500; -- 에러발생
END IF;
END;
109
서브프로그램서브 프로그램의 인자
IN OUT인자값을 서브프로그램에 전달하거나 호출 PL/SQL 문에
값을 반환시 사용
110
PROCEDURE calc_bonus (emp_id IN INTEGER, bonus IN OUT REAL) IS
hire_date DATE;
bonus_missing EXCEPTION;
BEGIN
SELECT sal * 0.10, hiredate INTO bonus, hire_date
FROM emp
WHERE empno = emp_id;
IF bonus IS NULL THEN
RAISE bonus_missing;
END IF;
IF MONTHS_BETWEEN(sysdate, hire_date) > 60 THEN
bonus := bonus + 500;
END IF;
EXCEPTION
WHEN bonus_missing THEN
END calc_bonus;
top related