-- 프로시져(Stored Procedure)
PL/SQL에서 가장 대표적인 구조인 스토어드 프로시져는 개발자가 자주 실행해야 하는 업무 흐름을 미리 작성하여 데이터베이스 내에 저장해 두었다가 필요할 때마다 호출하여 실행할 수 있다.
-- 프로시져 작성
CREATE [OR REPLACE] PROCEDURE 프로시져이름
[(
매개변수 IN 자료형, // 입력용, 인수에서는 자료형크기를 지정하면 안 된다.
매개변수 OUT 자료형, // 출력용
매개변수 IN OUT 자료형 // 입/출력용
)]
IS
[변수의 선언]
BEGIN
.............
[EXCEPTION]
.............
END;
IN 파라미터 : 호출자에 의해 프로시져로 전달되는 파라미터이며, '읽기' 전용의 값으로 프로시져는 이 파라미터의 값을 변경할 수 없다.(디폴트 모드)
OUT 파라미터 : 프로시져에서 값을 변경할 수 있고, '쓰기' 기능으로 프로시져가 정보를 호출자에게 돌려주는 기능이다. OUT 파라미터는 디폴트값을 지정할 수 없다.
IN OUT 파라미터 : 프로시져가 읽고 쓰는 작업을 동시에 할 수 있는 파라미터이다.
-- 주의
1) 프로시져 안에서는 INSERT, UPDATE, DELETE문을 사용하는 경우 자동 커밋이 되지 않으므로 COMMIT; 구문을 추가 해야 한다.
2) 프로시져에서 INSERT 문을 2개 이상 사용하여 데이터를 추가하는 경우 첫번째 INSERT문은 성공하고 두번째 INSERT 에서 추가를 실패하면 첫번째 INSERT는 자동으로 ROLLBACK 된다.
-- 테이블의 프로시져, 함수, 패키지 등 상호 참조되는 관계 확인
SELECT * FROM user_dependencies;
-- 소스확인
SELECT text FROM user_source;
-- 프로시져 목록 확인
SELECT object_name FROM user_procedures;
-- 프로시져 실행
EXEC[UTE] 프로시져이름[(인수, 인수)];
-- 프로시져 삭제
DROP PROCEDURE 프로시져이름;
* 테이블이 삭제된다고 연관된 프로시져가 삭제 되는것은 아니다.
하지만 테이블이 삭제된 상태에서 연관된 프로시져를 실행 하면 오류가 발생 한다.
=============================================================================================================================
--테이블 작성
1.테이블명 : test1
CREATE TABLE test1(
num NUMBER PRIMARY KEY
,name VARCHAR2(20)
,birth DATE
);
2.테이블명 : test2
CREATE TABLE test2(
num NUMBER PRIMARY KEY
,score NUMBER(3) NOT NULL
,pan VARCHAR2(10)
,CONSTRAINT fk_test2_hakbeon FOREIGN KEY (num) REFERENCES test1 (num)
);
3. 시퀀스 작성 -- 시퀀스는 num에 데이터 추가할떄마다 번호를 자동으로 붙여주는 기능을 한다.
CREATE SEQUENCE exam_seq
INCREMENT BY 1
START WITH 1
NOMAXVALUE
NOCYCLE
NOCACHE;
COMMIT;
SELECT * FROM tab;
SELECT * FROM user_sequences;
-- 데이터를 추가하는 프로시져 작성
CREATE OR REPLACE procedure insertEaxm
( -- 여기에 프로시져 실행문으로 입력받을 매개변수 입력
pname IN test1.name%TYPE -- %TYPE => test1테이블의 name컬럼의 타입을 그대로 가져오겠다는 단어
,pbirth IN test1.birth%TYPE
,pscore IN NUMBER --인수는 컬럼폭을 지정할수없다.
)
IS --여기에는 BEGIN에 사용될 변수 입력
vpan VARCHAR2(10);
vnum NUMBER;
BEGIN --실행문 입력
IF pscore >= 80 THEN
vpan:='우수';
ELSIF pscore >= 60 THEN
vpan:='보통';
ELSE
vpan:='노력';
END IF;
SELECT exam_seq.NEXTVAL INTO vnum FROM dual;
INSERT INTO test1(num, name, birth)
VALUES(vnum,pname,pbirth);
INSERT INTO test2(num,score,pan)
VALUES(vnum,pscore,vpan);
COMMIT;
END;
/
프로시져를 실행
EXEC insertEaxm('홍길동','2000-10-10',90); -- 프로시져의 매개변수 선언 순서대로 입력
EXEC insertEaxm('이이이','2000-09-10',70);
EXEC insertEaxm('후후후','2000-08-10',60);
EXEC insertEaxm('미미미','2000-07-10',70);
SELECT * FROM test1;
SELECT * FROM test2;
ROLLBACK;
-------------------------------------------------------------------------------------
-- 수정하는 프로시져 작성
-- 프로시져명 : updateExam
실행예 : EXEC updateExam(1,'홍길동','2000-10-10',75);
1번의 자료중 exam1과 exam2테이블의 정보를 수정.
단 기본키는 수정하지 않는다.
CREATE OR REPLACE procedure updateExam
(
pnum IN test1.num%TYPE
,pname IN test1.name%TYPE
,pbirth IN test1.birth%TYPE
,pscore IN NUMBER
)
IS
vpan VARCHAR2(10);
BEGIN
IF pscore >= 80 THEN
vpan:='우수';
ELSIF pscore >= 60 THEN
vpan:='보통';
ELSE
vpan:='노력';
END IF;
UPDATE test1 SET name=pname ,birth=pbirth WHERE num=pnum; --입력받은 pname,pbirth,pnum의 값을 name,birth,num에 대입하여 수정하라
UPDATE test2 SET score=pscore ,pan=vpan WHERE num=pname;
COMMIT;
END;
/
-- updateExam 프로시져 실행
EXEC updateExam(1,'홍길동','2000-10-10',75);
--=> 컬럼의 순서는 프로시져에서 생성한 컬럼 순서대로 써준다.
------------------------------------------------------------------------------------
-- 삭제하는 프로시져 작성
-- 프로시져명 : deleteExam
실행예 : EXEC deleteEXAM(1);
num이 1인 exam1과 exam2 테이블 자료 삭제
CREATE OR REPLACE procedure deleteExam
(
pnum IN test1.num%TYPE
)
IS
BEGIN
DELETE FROM test2 WHERE num=pnum;
DELETE FROM test1 WHERE num=pnum;
-- FOREIGN KEY 때문에 자식을 먼저 지우고 부모를 나중에 지워야한다.
COMMIT;
END;
/
-- deleteExam 프로시져 실행
EXEC deleteExam (1); --=> num 1의 값을 지운다. --=> 컬럼의 순서는 프로시져에서 생성한 컬럼 순서대로 써주지만 하나밖에 없으므로 신경안씀..
SELECT * FROM test1;
--프로시져 목록 확인
SELECT * FROM user_procedures;
--소스확인
SELECT * FROM user_source;
--상호참조관계 확인
SELECT * FROM user_dependencies;
--인지가 없는 프로시져 작성
CREATE OR REPLACE PROCEDURE selectAllExam
--여기에 인자가 없음
IS
BEGIN
FOR rec IN (SELECT a.num, name, birth, score, pan
FROM test1 a JOIN test2 b ON a.num=b.num) LOOP
DBMS_OUTPUT.PUT(rec.num || ' '); -- DBMS_OUTPUT.PUT => 자바의 System.out.print와 같다.
DBMS_OUTPUT.PUT(rec.name || ' ');
DBMS_OUTPUT.PUT(rec.birth || ' ');
DBMS_OUTPUT.PUT(rec.score || ' ');
DBMS_OUTPUT.PUT(rec.pan);
DBMS_OUTPUT.NEW_LINE();
END LOOP;
END;
/
EXEC selectAllExam;
SELECT * FROM test1;
'오라클' 카테고리의 다른 글
상관하위부 질의 (0) | 2013.06.06 |
---|---|
프로시져의 SYS_REFCURSOR 예제 (0) | 2013.06.05 |
PL/SQL (0) | 2013.06.04 |
트랜잭션 (0) | 2013.06.04 |
inline view (또는 subquery), WITH (0) | 2013.06.03 |