본문 바로가기

📚Study Note/ORACLE

[ ORACLE ] CREATE OR REPLACE PROCEDURE 프로시저명

-- ■■■■  PROCEDURE(프로시저)  ■■■■

-- 1. PL/SQL 에서 가장 대표적인 구조인 스토어드 프로시저는
-- 개발자가 자주 작성해야 하는 업무의 흐름을
-- 미리 작성하여 데이터베이스 내에 저장해 두었다가
-- 필요할 때 마다 호출하여 실행할 수 있도록 처리해주는 구문이다.

2. 형식 및 구조

CREATE [OR REPLACE] PROCEDURE 프로시저명
[(매개변수 IN 데이터타입
, 매개변수 OUT 데이터타입
, 매개변수 INOUT 데이터타입
)]
IS
    [주요 변수 선언;]
BEGIN
    -- 실행구문;
    ...
    [EXCEPTION
        -- 예외 처리 구문;]
END;

*/

-- ※ FUNCTION 과 비교했을 때, 
-- 『RETURN』 반환자료형 부분이 존재하지 않으며,
-- 『RETURN 문 자체도 존재하지 않으며,
-- 프로시저 실행 시 넘겨주게 되는 매개변수의 종류는
-- IN, OUT, INOUT 으로 구분된다.


--3. 실행(호출)
/*
EXEC[UTE] 프로시저명[(인수1, 인수2)]

*/

 

 

-- ※ 프로시저 실습 진행을 위한 테이블 생성 및 데이터 입력
-- ● INSERT 쿼리 실행을 프로시저로 작성(INSERT 프로시저)


-- 실습 테이블 생성(TBL_STUDENTS)
CREATE TABLE TBL_STUDENTS
(ID     VARCHAR2(10)
,NAME   VARCHAR2(40)
,TEL    VARCHAR2(20)
,ADDR   VARCHAR2(100)
);
--==>> Table TBL_STUDENTS이(가) 생성되었습니다.

-- 실습 테이블 생성(TBL_IDPW)
CREATE TABLE TBL_IDPW
(ID     VARCHAR2(10)
,PW     VARCHAR2(20)
,CONSTRAINT INPW_ID_PK PRIMARY KEY(ID)
);
--==>>Table TBL_IDPW이(가) 생성되었습니다.


-- 한 명의 학생 정보 등록 두 테이블에 데이터 입력
INSERT INTO TBL_STUDENTS(ID,NAME,TEL,ADDR)
VALUES('superman','박정준','010-1111-1111','제주도 서귀포시');
INSERT INTO TBL_IDPW(ID,PW)
VALUES('superman','java006$');


SELECT *
FROM TBL_STUDENTS;
SELECT *
FROM TBL_IDPW;


-- 위의 업무를 프로시저(INSERT프로시저, 입력 프로시저)를 생성하게 되면
EXEC PRC_STUDENTS_INSERT('happyday','java006$','김서현','010-2222-2222','서울 마포구')

-- 이와 같은 구문 한 줄로 양쪽 테이블에 데이터를 모두 제대로 입력할 수 있다.

 

 

 

 

-- ● INSERT 쿼리 실행을 프로시저로 작성(INSERT 프로시저)
-- 실습 테이블 생성(TBL_STUDENTS) ▶ 20210408_04_SCOTT.SQL 참고
-- 실습 테이블 생성(TBL_IDPW) ▶ 20210408_04_SCOTT.SQL 참고

-- 프로시저 생성

-- 프로시저명 : PRC_STUDENTS_INSERT(아이디, 패스워드, 이름, 전화번호, 주소)


CREATE OR REPLACE PROCEDURE PRC_STUDENTS_INSERT
()
IS
BEGIN
END;

----------------

CREATE OR REPLACE PROCEDURE PRC_STUDENTS_INSERT
(   V_ID    IN TBL_STUDENTS.ID%TYPE
,   V_PW    IN TBL_IDPW.PW%TYPE
,   V_NAME  IN TBL_STUDENTS.NAME%TYPE
,   V_TEL   IN TBL_STUDENTS.TEL%TYPE
,   V_ADDR  IN TBL_STUDENTS.ADDR%TYPE

)
IS
    -- 주요 변수 선언
BEGIN
    -- TBL_IDPW 테이블에 데이터 입력
    
    INSERT INTO TBL_IDPW(ID,PW)
    VALUES(V_ID,V_PW);
    -- TBL_STUDENTS 테이블에 데이터 입력
    INSERT INTO TBL_STUDENTS(ID,NAME,TEL,ADDR)
    VALUES(V_ID,V_NAME,V_TEL,V_ADDR);
    
    COMMIT;
    
END;

--==>>Procedure PRC_STUDENTS_INSERT이(가) 컴파일되었습니다.

 

-- ● 생성한 프로시저(PRC_STUDENTS_INSERT)가 제대로 작동하는지의 여부 확인
-- 
EXEC PRC_STUDENTS_INSERT('happyday','java006$','김서현','010-2222-2222','서울 마포구');
--==>PL/SQL 프로시저가 성공적으로 완료되었습니다.

/*
superman	    박정준	010-1111-1111	제주도 서귀포시
happyday	김서현	010-2222-2222	서울 마포구

superman	    java006$
happyday	java006$

두 테이블 모두에 '김서현'데이터가 잘 들어가있다.
*/

 

 

실습을 위한 테이블 생성

-- ● 학번, 이름, 국어점수ㅡ 영어점수 수학점수 데이터 입력받는 테이블 생성
CREATE TABLE TBL_SUNGJUK
(HAKBUN     NUMBER
,NAME       VARCHAR2(40)
,KOR        NUMBER(3)
,ENG        NUMBER(3)
,MAT        NUMBER(3)
,CONSTRAINT SUNGJUK_HAKBUN_PK PRIMARY KEY(HAKBUN)
);
--==>>Table TBL_SUNGJUK이(가) 생성되었습니다.

-- 생성된 테이블에 컬럼 구조 추가

-- (총점 → TOT, 평균 AVG 등급 GRADE 로)

ALTER TABLE TBL_SUNGJUK
ADD(TOT NUMBER(3), AVG  NUMBER(4,1), GRADE CHAR);
--==>>Table TBL_SUNGJUK이(가) 변경되었습니다.


-- ※ 여기서 추가한 컬럼에 대한 항목들은 프로시저 실습을 위해 추가하는 것일 뿐
-- 실제 테이블 구조에 적합하지 않다.(국영수 점수로 등급 평균 총점 다 알 수 있는 것이기 때문에)


-- ● 변경된 테이블 구조 확인
DESC TBL_SUNGJUK;
/*
이름     널?       유형           
------ -------- ------------ 
HAKBUN NOT NULL NUMBER       
NAME            VARCHAR2(40) 
KOR             NUMBER(3)    
ENG             NUMBER(3)    
MAT             NUMBER(3)    
TOT             NUMBER(3)    
AVG             NUMBER(4,1)  
GRADE           CHAR(1)   
*/

 

 

테이블을 토대로 프로시저 구성

-- ● 데이터입력 시 
-- 특정 항목의 데이터(학번, 이름, 국어점수,영어점수, 수학점수)만 입력하면
-- 총점, 평균, 등급 항목이 함께 입력 처리될 수 있는 프로시저를 작성한다(생성한다.)

-- 프로시저명 : PRC_SUNGJUK_INSERT()

/*
실행 예

EXEC PRC_SUNGJUK_INSERT(1, '조은선',90,80,70);

프로시저 호출로 처리된 결과)
학번 이름 국어점수 영어점수  수학점수 총점 평균 등급
1   조은선     90      80      70      240   80    B




*/

CREATE OR REPLACE PROCEDURE PRC_SUNGJUK_INSERT
(V_HAKBUN   IN TBL_SUNGJUK.HAKBUN%TYPE
,V_NAME     IN TBL_SUNGJUK.NAME%TYPE
,V_KOR      IN TBL_SUNGJUK.KOR%TYPE
,V_ENG      IN TBL_SUNGJUK.ENG%TYPE
,V_MAT      IN TBL_SUNGJUK.MAT%TYPE
)
IS
    V_TOT  NUMBER; --IN TBL_SUNGJUK.TOT%TYPE;
    V_AVG  NUMBER; --IN TBL_SUNGJUK.AVG%TYPE;
    V_GRADE CHAR;--IN TBL_SUNGJUK.GRADE%TYPE;
BEGIN
    -- 총점, 평균, 등급 구하기
    V_TOT:= V_KOR + V_ENG + V_MAT;
    V_AVG:= (V_TOT)/3;
    --V_GRADE:= DECODE(TRUNC(V_AVG,-1),90,'A',80,'B',70,'C',60,'D','F');
    
    V_GRADE:= CASE TRUNC(V_AVG,-1) WHEN 100 THEN 'A'
                                   WHEN 90 THEN 'A' 
                                   WHEN 80 THEN 'B'
                                   WHEN 70 THEN 'C'
                                   WHEN 60 THEN 'D'
                                   ELSE 'F' 
              END;
    -- 테이블에 데이터 삽입
    INSERT INTO TBL_SUNGJUK (HAKBUN, NAME, KOR, ENG, MAT, TOT, AVG, GRADE)
    VALUES(V_HAKBUN, V_NAME, V_KOR, V_ENG, V_MAT, V_TOT, V_AVG, V_GRADE);  
    

END;
--==>>Procedure PRC_SUNGJUK_INSERT이(가) 컴파일되었습니다.

 

위에서 만든 PRC_SUNGJUK_INSERT 의 생성 방식과 다른 방식

CREATE OR REPLACE PROCEDURE PRC_SUNGJUK_INSERT
(V_HAKBUN   IN TBL_SUNGJUK.HAKBUN%TYPE
,V_NAME     IN TBL_SUNGJUK.NAME%TYPE
,V_KOR      IN TBL_SUNGJUK.KOR%TYPE
,V_ENG      IN TBL_SUNGJUK.ENG%TYPE
,V_MAT      IN TBL_SUNGJUK.MAT%TYPE
)
IS
    V_TOT   TBL_SUNGJUK.TOT%TYPE;
    V_AVG   TBL_SUNGJUK.AVG%TYPE;
    V_GRADE TBL_SUNGJUK.GRADE%TYPE;
BEGIN
    -- 총점, 평균, 등급 구하기
    V_TOT:= V_KOR + V_ENG + V_MAT;
    V_AVG:= (V_TOT)/3;
    --V_GRADE:= DECODE(TRUNC(V_AVG,-1),90,'A',80,'B',70,'C',60,'D','F');
    IF V_AVG>=90     THEN V_GRADE:='A';
    ELSIF V_AVG>=80  THEN V_GRADE:='B';
    ELSIF V_AVG>=70  THEN V_GRADE:='C';
    ELSIF V_AVG>=60  THEN V_GRADE:='D';
    ELSE V_GRADE:='F';
    END IF;
    

    -- 테이블에 데이터 삽입
    INSERT INTO TBL_SUNGJUK (HAKBUN, NAME, KOR, ENG, MAT, TOT, AVG, GRADE)
    VALUES(V_HAKBUN, V_NAME, V_KOR, V_ENG, V_MAT, V_TOT, V_AVG, V_GRADE);  
    
    COMMIT;-- ★
END;

INSERT INTO TABLE명 이후에는 꼭 COMMIT 해주기!

 

 

SELECT TRUNC(69,-1)
FROM DUAL;
--==>> 성적 범위 잡으려고 69 점 60 점으로 만들어주려고 실험해본거

-- 생성한 프로시저(PRC_SUNGJUK_INSERT) 가 제대로 작동하는지의 여부 확인
-- → 프로시저 호출
EXEC PRC_SUNGJUK_INSERT(1, '조은선',90,80,70);
EXEC PRC_SUNGJUK_INSERT(2, '다람이',100,100,100);
EXEC PRC_SUNGJUK_INSERT(3, '징징이',50,40,20);
EXEC PRC_SUNGJUK_INSERT(4, '이상해',90,80,70);
SELECT *
FROM TBL_SUNGJUK;
/*
HAKBUN	NAME	KOR	ENG	MAT	TOT	AVG	GRADE
1	    조은선	50	50	50	150	50	    F
2	    다람이	100	100	100	300	100	    A
3	    징징이	50	40	20	110	36.7	F
4	    이상해	90	80	70	240	80	    B
*/

 

-- ● TBL_SUNGJUK 테이블에서
-- 특정 학생의 점수(학번, 국어점수, 영어점수, 수학점수)
-- 데이터 수정 시 총점, 평균 , 등급까지 수정하는 프로시저를 작성한다.

-- 프로시저명 : PRC_SUNGJUK_UPDATE


/*
실행 예)
EXEC PRC_SUNGJUK_UPDATE(1,50,50,50);

호출로 처리된 결과 
학번 이름 국어점수 영어점수  수학점수 총점 평균 등급
1   이상해    50     50      50      150   50    F

*/


CREATE OR REPLACE PROCEDURE PRC_SUNGJUK_UPDATE
(V_HAKBUN   IN TBL_SUNGJUK.HAKBUN%TYPE
,V_KOR      IN TBL_SUNGJUK.KOR%TYPE
,V_ENG      IN TBL_SUNGJUK.ENG%TYPE
,V_MAT      IN TBL_SUNGJUK.MAT%TYPE
)
IS
    V_TOT TBL_SUNGJUK.TOT%TYPE;
    V_AVG TBL_SUNGJUK.AVG%TYPE;
    V_GRADE TBL_SUNGJUK.GRADE%TYPE;

BEGIN
    -- 새로운 총점,평균,등급 구하기
    V_TOT:= V_KOR + V_ENG + V_MAT;
    V_AVG:= (V_TOT)/3;
    
    IF V_AVG>=90     THEN V_GRADE:='A';
    ELSIF V_AVG>=80  THEN V_GRADE:='B';
    ELSIF V_AVG>=70  THEN V_GRADE:='C';
    ELSIF V_AVG>=60  THEN V_GRADE:='D';
    ELSE V_GRADE:='F';
    END IF;
    -- 테이블 업데이트하기
    UPDATE TBL_SUNGJUK
    SET KOR=V_KOR, ENG=V_ENG, MAT=V_MAT, TOT=V_TOT,AVG=V_AVG,GRADE=V_GRADE
    WHERE HAKBUN=V_HAKBUN;
    
    -- 업데이트 결과 COMMIT 하기
    COMMIT;
    

END;

--===>>Procedure PRC_SUNGJUK_UPDATE이(가) 컴파일되었습니다.


 

 

 

-- 생성한 프로시저(PRC_SUNGJUK_UPDATE) 가 제대로 작동하는지의 여부 확인
-- → 프로시저 호출

EXEC PRC_SUNGJUK_UPDATE(1,50,50,50);


SELECT *
FROM TBL_SUNGJUK;
/*1	조은선	50	50	50	150	50	F

--==>> 기존 90 80 70 점수에서 50 50 50 으로 바뀌고 그에따라 총점,평균,등급도 변경되었다. 
*/

 

 

 

 

---● TBL_STUDENTS 테이블에서 
-- 전화번호와 주소 데이터를 수정하는 프로시저를 작성한다.
-- 단, ID와 PW 가 일치하는 경우에는 수정을 진행할 수 있도록 한다.
-- 프로시저 명 : PRC_STUDENTS_UPDATE


/*
실행 예)
EXEC PRC_STUDENTS_UPDATE('superman','java006$','010-9999-9999','경기 일산');

프로시저 호출로 처리된 결과
superman  박정준  010-9999-9999 경기 일산



*/


CREATE OR REPLACE PROCEDURE PRC_STUDENTS_UPDATE
(
-- 매개변수로 받을 것 : 아이디 비밀번호 전화번호 주소
V_ID IN TBL_IDPW.ID%TYPE
,V_PW IN TBL_IDPW.PW%TYPE
,V_TEL IN TBL_STUDENTS.TEL%TYPE
,V_ADDR IN TBL_STUDENTS.TEL%TYPE
)
IS
-- 변수 선언 : 따로 할 것이 ,,, 없다!
BEGIN
-- 실행 연산 : "아이디 비밀번호가 TBL_IDPW 와 일치한다면" TBL_STUDENTS를 업데이트 한후 COMMIT 한다.
    
   
    UPDATE TBL_STUDENTS
    SET TEL = V_TEL, ADDR=V_ADDR
    WHERE ID=V_ID AND (SELECT PW
              FROM TBL_IDPW
              WHERE ID=V_ID)=V_PW;
    
    COMMIT;
END;
--==>>Procedure PRC_STUDENTS_UPDATE이(가) 컴파일되었습니다.





 

 

 

 

EXEC PRC_STUDENTS_UPDATE('superman','java006$','010-9999-9999','경기 일산');
--==>>PL/SQL 프로시저가 성공적으로 완료되었습니다.

SELECT * 
FROM TBL_STUDENTS;
/*
superman	    박정준	010-9999-9999	경기 일산
happyday	김서현	010-2222-2222	서울 마포구
*/

--만약 다른 PW를 입력한다면????????????

EXEC PRC_STUDENTS_UPDATE('superman','javajava','010-9999-9999','경기 일산');
--==>>PL/SQL 프로시저가 성공적으로 완료되었습니다.
/*
superman	    박정준	010-9999-9999	경기 일산
happyday	김서현	010-2222-2222	서울 마포구
*/
-- 데이터가 변경되지 않았다. 

 

 

 

근속년수 구하기 

MONTHS_BETWEEN 활용하기

예를 들어 2000년 11월에  입사했으면 현재 21년 4월을 기준으로 약 20.4년을 근무했다.

 

소수점 한 자리까지 나타내기 위해서 

변수의 타입을 NUMBER(3,1)로 지정해주거나

TO_CHAR(□ , '999.9') 로 지정

SELECT MONTHS_BETWEEN(SYSDATE,TO_DATE('2000-11-12','YYYY-MM-DD'))/12
FROM DUAL;

--20.4112047926622859418558343289526085225



SELECT TO_CHAR(MONTHS_BETWEEN(SYSDATE,TO_DATE('2000-11-12','YYYY-MM-DD'))/12,'999.9')
FROM DUAL;
--   20.4