카테고리 없음

[OracleStudy] 20240221 [과제 제출] - Final Project Job Scheduler

Jelly-fish 2024. 2. 22. 08:55

OracleStudy

[제작한 Oracle Job Scheduler 설명]
- Final Project 에서 우리 팀이 필요한 Oracle Job Scheduler 는, 개설 신청글의 목표 모집인원수가 모집 종료일에 모두 채워졌을 경우 개설 확정 테이블에 새로운 레코드를 삽입해 주는 스케줄러이다.

이를 위해 제작한 프로시저는 `C_PROJECT_PRC` 이다.
이 프로시저 내부에서 처리하는 Logic은

① 오늘이 멤버 모집 종료일인 개설 신청글의 개설 신청 코드 `APP_OPENCODE`를 CURSOR로 뽑아낸다.
  -- 커서 선언 『개설신청 코드 커서』
    CURSOR OPENCODE_SELECT
    IS
    SELECT APP_OPENCODE
    FROM APP_OPENING
    WHERE TO_CHAR(APP_STARTDATE-1, 'YYYY-MM-DD')
          = TO_CHAR(SYSDATE, 'YYYY-MM-DD');
    --    ★──────────────────
    --      『프로젝트 시작일 하루 전(모집 종료일)이 현재 날짜(SYSDATE)』인
    --      개설 신청글의 개설 신청 코드를 받아온다.​


② 커서를 열어서 `LOOP` 를 통해 반복하기 시작한다. 루프문 내부에서 개설 확정 테이블 `C_PROJECT`의 개설 확정 코드 `CP_CODE`를 `NVL(MAX(CP_CODE), 0) + 1` 로 생성한다.
 LOOP
        FETCH OPENCODE_SELECT INTO V_APP_OPENCODE;
        
        EXIT WHEN OPENCODE_SELECT%NOTFOUND;
        
        --============================================
        -- [다음번 프로젝트 개설 확정 코드 구하기]
        --============================================
        SELECT NVL(MAX(CP_CODE), 0) + 1 INTO V_CP_CODE
        FROM C_PROJECT;​



③ 만약, 특정 프로젝트 개설 신청의 모집 인원수가 모두 채워졌다면 개설 확정 테이블 `C_PROJECT`에  개설확정일자 `CP_DATE`를 오늘 `SYSDATE`로, 개설 신청 코드 `APP_OPENCODE`를 해당 개설 신청글의 개설신청코드로 구성하여 레코드를 삽입한다.
LOOP
        FETCH OPENCODE_SELECT INTO V_APP_OPENCODE;
        
        EXIT WHEN OPENCODE_SELECT%NOTFOUND;
        
        --============================================
        -- [다음번 프로젝트 개설 확정 코드 구하기]
        --============================================
        SELECT NVL(MAX(CP_CODE), 0) + 1 INTO V_CP_CODE
        FROM C_PROJECT;
        
        --================================================
        -- 1. 특정 개설신청 글의 현재 모집 인원수 구하기
        --================================================
        SELECT COUNT(*) INTO V_PERSONNEL
        FROM APP_OPENING AO
             INNER JOIN ROLE_COMPOSITION RC
             ON AO.APP_OPENCODE = RC.APP_OPENCODE
             INNER JOIN MEMBER_APPLY MA
             ON RC.RC_CODE = MA.RC_CODE
             INNER JOIN A_RESULT AR
             ON MA.AR_CODE = AR.AR_CODE
        WHERE AO.APP_OPENCODE = V_APP_OPENCODE
              AND AR.AR_CODE = 1;
                  -- 멤버 지원이 성공한 경우에만 인원수 반영
                  
        --================================================
        -- 2. 목표 모집 인원수 구하기
        --================================================
        SELECT MEMBER_NUMBER INTO V_MEMBER_NUMBER
        FROM APP_OPENING
        WHERE APP_OPENCODE = V_APP_OPENCODE;
    
        --=================================================================
        -- 3. 현재 인원이 목표 모집 인원수가 같을 때 테이블에 INSERT 처리.
        --=================================================================
        IF (V_PERSONNEL = V_MEMBER_NUMBER)
        --  ===========   ==============
        --      ⓐ              ⓑ
        --*******************************************
        --  【ⓐ : 현재까지 모집 완료한 인원수】
        --  【ⓑ : 프로젝트 목표 모집 인원수】
        --*******************************************
            THEN
            INSERT INTO C_PROJECT (CP_CODE, CP_DATE, APP_OPENCODE)
            VALUES(V_CP_CODE, SYSDATE, V_APP_OPENCODE);
            
            COMMIT;
        ELSE
            DBMS_OUTPUT.PUT_LINE('[※프로젝트 목표 모집 인원이 채워지지 않았습니다.※]');
        END IF;
        
        
    END LOOP;
    
    CLOSE OPENCODE_SELECT;
    
    
    EXCEPTION
            WHEN OTHERS THEN ROLLBACK;






위의 프로시저를 매일 오후 2시에 실행하기 위해 스케줄러를 등록한다.
이 스케줄러의 이름은 `PJ_CONFIRM_SCHEDULE` 로 정하였고
동작 시작일 `START_DATE`는 `2024-02-18 14:00:00`으로 설정하였다.
반복 횟수 `REPEAT_INTERVAL`은 `FREQ=DAILY; INTERVAL=1` 로 설정하여 하루에 한 번, 오후 2시가 될 때마다 해당 스케줄을 실행하도록 하였으며 종료일을 설정하지 않기위해 `END_DATE => NULL`로 설정하였다.
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩『스케줄러 잡 등록』▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

BEGIN
    DBMS_SCHEDULER.CREATE_SCHEDULE
    ( SCHEDULE_NAME     => 'PJ_CONFIRM_SCHEDULE'
    , START_DATE        => TO_DATE('2024-02-18 14:00:00', 'YYYY-MM-DD HH24:MI:SS')
    --『START_DATE』     : 2024-02-18 일자의 오후 2시마다, 
    --                      모집인원이 채워진 개설신청글을 개설 확정 테이블로 이동한다.
    , END_DATE          => NULL
    , REPEAT_INTERVAL   => 'FREQ=DAILY; INTERVAL=1'
    --『REPEAT_INTERVAL』: 매일 오후 2시마다, 개설 확정 테이블을 업데이트한다.
    );
END;

--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩​


이어서 프로그램을 등록할 때, 위에서 제작한 프로시저를 `STORED_PROCEDURE` 로 설정하였다.

 

 


 

JOB_SCHEDULER_C_scott(김지민).sql

 

SELECT USER
FROM DUAL;
--==>> SCOTT

-- FINAL PROJECT 일부 테이블 샘플링

-- 프로시저 구성

-- 자동화 업무 수행

-- 테스트 및 확인


/*
■■■■■[필요한 테이블 - 순서 구성]■■■■■

    ① 일반 회원 테이블 - 강혜성
    ② 개설 신청 테이블 - 이윤수
    ③ 직무 테이블 - 길현욱
    ④ 팀원별 직무 구성 테이블 - 김지민
    ⑤ 멤버 지원 테이블 - 정한울
    ⑥ 지원 결과 테이블 - 길현욱
    ⑦ 프로젝트 확정 테이블 - 박범구

■■■■■■■■■■■■■■■■■■■■■■■■
*/



--===================================================
-- ① 『일반 회원 테이블』
--===================================================

CREATE TABLE MEMBERS (
    MEMBER_CODE     NUMBER
  , MEM_ID          VARCHAR2(50)
  , MEM_PW          VARCHAR2(50)
  , MEM_NICKNAME    VARCHAR2(50)
  , JOIN_DATE       DATE    DEFAULT SYSDATE
)

INSERT INTO MEMBERS VALUES(1, 'ID1', 'PW1', 'NN1', SYSDATE);
INSERT INTO MEMBERS VALUES(2, 'ID2', 'PW2', 'NN2', SYSDATE);
INSERT INTO MEMBERS VALUES(3, 'ID3', 'PW3', 'NN3', SYSDATE);
INSERT INTO MEMBERS VALUES(4, 'ID4', 'PW4', 'NN4', SYSDATE);
INSERT INTO MEMBERS VALUES(5, 'ID5', 'PW5', 'NN5', SYSDATE);
INSERT INTO MEMBERS VALUES(6, 'ID6', 'PW6', 'NN6', SYSDATE);
INSERT INTO MEMBERS VALUES(7, 'ID7', 'PW7', 'NN7', SYSDATE);

ALTER TABLE MEMBERS ADD PRIMARY KEY(MEMBER_CODE);

SELECT *
FROM MEMBERS;
--===================================================
--===================================================




--===================================================
-- ② 『개설 신청 테이블』
--===================================================
CREATE TABLE APP_OPENING
( APP_OPENCODE      NUMBER
, APP_TITLE         VARCHAR(100) NOT NULL
, APP_MINCONTENT    VARCHAR(100)
, APP_STARTDATE     DATE
, APP_ENDDATE       DATE
, APP_CONTENT       VARCHAR(1000)
, APP_OPENDATE      DATE DEFAULT SYSDATE
, MEMBER_NUMBER     NUMBER
, VIEW_NUMBER       NUMBER
, MEMBER_CODE       NUMBER
, CONSTRAINT FK_MEMBER_CODE FOREIGN KEY(MEMBER_CODE)
                    REFERENCES MEMBERS(MEMBER_CODE)
);

ALTER TABLE APP_OPENING ADD PRIMARY KEY(APP_OPENCODE);


INSERT INTO APP_OPENING
VALUES(1,'가나다','첫번째', SYSDATE, SYSDATE+1 ,'첫번째다다',SYSDATE, 5, 5, 1);
INSERT INTO APP_OPENING
VALUES(2,'가가가','두번째', SYSDATE, SYSDATE+2 ,'두번째다다',SYSDATE, 5, 5, 2);
INSERT INTO APP_OPENING
VALUES(3,'나나나','세번째', SYSDATE, SYSDATE+3 ,'세번째다다',SYSDATE, 5, 5, 3);
INSERT INTO APP_OPENING
VALUES(4,'다다다','네번째', SYSDATE, SYSDATE+4 ,'네번째다다',SYSDATE, 5, 5, 4);

--===================================================
--===================================================


--===================================================
-- ③ 『직무 테이블』
--===================================================

-- 직무 테이블 생성 
CREATE TABLE MEMBER_ROLE
( MR_CODE NUMBER(3)
, ROLE VARCHAR2(50)
);


ALTER TABLE MEMBER_ROLE ADD PRIMARY KEY(MR_CODE);


-- 데이터 삽입
INSERT INTO MEMBER_ROLE (MR_CODE, ROLE) VALUES (1, '팀장');
INSERT INTO MEMBER_ROLE (MR_CODE, ROLE) VALUES (2, '프론트');
INSERT INTO MEMBER_ROLE (MR_CODE, ROLE) VALUES (3, '백엔드');

--===================================================
--===================================================


--===================================================
-- ④ 『팀원별 직무 구성 테이블』
--===================================================

CREATE TABLE ROLE_COMPOSITION
( RC_CODE       NUMBER
, RC_NUMBER     NUMBER
, APP_OPENCODE  NUMBER
, MR_CODE       NUMBER
, CONSTRAINT R_COMPOSITION_RC_CODE_PK PRIMARY KEY(RC_CODE)
, CONSTRAINT R_COMPOSITION_APP_OPENCODE_FK FOREIGN KEY (APP_OPENCODE)
                                           REFERENCES APP_OPENING(APP_OPENCODE)
, CONSTRAINT R_COMPOSITION_MR_CODE_FK FOREIGN KEY (MR_CODE)
                                      REFERENCES MEMBER_ROLE(MR_CODE)
);

-- 『팀원별 직무 구성 데이터 삽입』

INSERT INTO ROLE_COMPOSITION(RC_CODE, RC_NUMBER, APP_OPENCODE, MR_CODE)
VALUES(1, 3, 1, 1);
INSERT INTO ROLE_COMPOSITION(RC_CODE, RC_NUMBER, APP_OPENCODE, MR_CODE)
VALUES(2, 2, 1, 2);
INSERT INTO ROLE_COMPOSITION(RC_CODE, RC_NUMBER, APP_OPENCODE, MR_CODE)
VALUES(3, 4, 2, 1);
INSERT INTO ROLE_COMPOSITION(RC_CODE, RC_NUMBER, APP_OPENCODE, MR_CODE)
VALUES(4, 1, 2, 2);


--===================================================
--===================================================



--===================================================
-- ⑤ 『멤버 지원 테이블』
--===================================================
CREATE TABLE MEMBER_APPLY
( MA_CODE       NUMBER PRIMARY KEY
, MA_CONTENT    VARCHAR2(1000)
, MA_DATE       DATE
, MAD_DATE      DATE
, MEMBER_CODE   NUMBER REFERENCES MEMBERS(MEMBER_CODE)
, RC_CODE       NUMBER REFERENCES ROLE_COMPOSITION(RC_CODE)       
, AR_CODE       NUMBER REFERENCES A_RESULT(AR_CODE)
);

INSERT INTO MEMBER_APPLY (MA_CODE, MA_CONTENT, MA_DATE, MEMBER_CODE, RC_CODE, AR_CODE) VALUES(1, '열심히 할게용!!', SYSDATE, 1, 1, 1);
INSERT INTO MEMBER_APPLY (MA_CODE, MA_CONTENT, MA_DATE, MEMBER_CODE, RC_CODE, AR_CODE) VALUES(2, '뽑지마라', SYSDATE, 2, 1, 1);
INSERT INTO MEMBER_APPLY (MA_CODE, MA_CONTENT, MA_DATE, MEMBER_CODE, RC_CODE, AR_CODE) VALUES(3, '너 내 동료가 돼라', SYSDATE, 3, 1, 1);
INSERT INTO MEMBER_APPLY (MA_CODE, MA_CONTENT, MA_DATE, MEMBER_CODE, RC_CODE, AR_CODE) VALUES(4, '테스트~!!!', SYSDATE, 4, 2, 1);
INSERT INTO MEMBER_APPLY (MA_CODE, MA_CONTENT, MA_DATE, MEMBER_CODE, RC_CODE, AR_CODE) VALUES(5, '같이 해봐요', SYSDATE, 5, 2, 3);
INSERT INTO MEMBER_APPLY (MA_CODE, MA_CONTENT, MA_DATE, MEMBER_CODE, RC_CODE, AR_CODE) VALUES(6, '같이 해봐요2', SYSDATE, 5, 2, 1);

--INSERT INTO MEMBER_APPLY (MA_CODE, MA_CONTENT, MA_DATE, MEMBER_CODE, RC_CODE, AR_CODE) VALUES(6, '지원 2-1', SYSDATE, 5, 2, 3);
--INSERT INTO MEMBER_APPLY (MA_CODE, MA_CONTENT, MA_DATE, MEMBER_CODE, RC_CODE, AR_CODE) VALUES(7, '지원 2-2', SYSDATE, 5, 2, 3);
--INSERT INTO MEMBER_APPLY (MA_CODE, MA_CONTENT, MA_DATE, MEMBER_CODE, RC_CODE, AR_CODE) VALUES(8, '지원 2-3', SYSDATE, 5, 2, 3);

--===================================================
--===================================================


--===================================================
-- ⑥ 『지원 결과 테이블』
--===================================================

-- 지원 결과 테이블 생성 
CREATE TABLE A_RESULT
( AR_CODE NUMBER
, A_RESULT VARCHAR2(50)
, CONSTRAINT AR_CODE_PK PRIMARY KEY(AR_CODE)
);
--==>> Table A_RESULT이(가) 생성되었습니다.

-- 데이터 삽입 
INSERT INTO A_RESULT (AR_CODE, A_RESULT) VALUES (1, '성공');
INSERT INTO A_RESULT (AR_CODE, A_RESULT) VALUES (2, '실패');
INSERT INTO A_RESULT (AR_CODE, A_RESULT) VALUES (3, '보류');


--===================================================
--===================================================



--===================================================
-- ⑦ 『프로젝트 확정 테이블』
--===================================================
CREATE TABLE C_PROJECT
( CP_CODE                  NUMBER
, CP_DATE                   DATE
, APP_OPENCODE        NUMBER
, CONSTRAINT C_CODE_PK PRIMARY KEY(CP_CODE)
, CONSTRAINT APP_OPENCODE_FK FOREIGN KEY(APP_OPENCODE) REFERENCES APP_OPENING(APP_OPENCODE)
);

INSERT INTO C_PROJECT (CP_CODE, CP_DATE, APP_OPENCODE) VALUES(1, SYSDATE, 1);
INSERT INTO C_PROJECT (CP_CODE, CP_DATE, APP_OPENCODE) VALUES(2, SYSDATE, 2);

--===================================================
--===================================================



--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩【현재까지 모집 완료한 인원수 구하기】▩▩▩
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

SELECT COUNT(*)
FROM APP_OPENING AO
     INNER JOIN ROLE_COMPOSITION RC
     ON AO.APP_OPENCODE = RC.APP_OPENCODE
     INNER JOIN MEMBER_APPLY MA
     ON RC.RC_CODE = MA.RC_CODE
     INNER JOIN A_RESULT AR
     ON MA.AR_CODE = AR.AR_CODE
WHERE AO.APP_OPENCODE = 1
      AND AR.AR_CODE = 1;

--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

      
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩【목표 모집 인원수 구하기】▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

SELECT MEMBER_NUMBER
FROM APP_OPENING
WHERE APP_OPENCODE = 1;

--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩



--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩【다음번 프로젝트 확정 코드 구하기】▩▩▩▩
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

SELECT NVL(MAX(CP_CODE), 0) + 1 AS NEXT_CP_CODE
FROM C_PROJECT;

--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩


--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩
--▩【모집기간이 종료된 프로젝트 개설신청코드 구하기】▩
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

SELECT APP_OPENCODE
FROM APP_OPENING
WHERE TO_CHAR(APP_STARTDATE-1, 'YYYY-MM-DD')
      = TO_CHAR(SYSDATE, 'YYYY-MM-DD');

--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩      

--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩【테이블 조회】▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

-- 1. 일반 회원
SELECT *
FROM MEMBERS;

-- 2. 개설 신청
SELECT *
FROM APP_OPENING;


--★[업데이트를 한 이후에, 반드시 COMMIT을 해야 JOB에 반영된다!]
--=============================================================
--============[테스트용 개설 신청 업데이트 구문]===============
--=============================================================
UPDATE APP_OPENING
SET APP_STARTDATE = TO_DATE('2024-02-27', 'YYYY-MM-DD');

COMMIT;
--=============================================================


-- 3. 직무 
SELECT *
FROM MEMBER_ROLE;

-- 4. 팀원별 직무 구성
SELECT *
FROM ROLE_COMPOSITION;

-- 5. 멤버 지원
SELECT *
FROM MEMBER_APPLY;

-- 6. 멤버 지원 결과
SELECT *
FROM A_RESULT;

-- 7. 프로젝트 개설 확정
SELECT *
FROM C_PROJECT;

--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩


--==================================================
-- [화면에 결과를 출력하기 위해 SERVEROUTPUT ON]
--==================================================
SET SERVEROUTPUT ON;
--==================================================



--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩『프로젝트 개설 확정 프로시저 생성』▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

CREATE OR REPLACE PROCEDURE C_PROJECT_PRC
IS
    -- 다음번 프로젝트 개설 확정 코드
    V_CP_CODE          C_PROJECT.CP_CODE%TYPE;
    
    -- 프로젝트 개설신청 코드
    V_APP_OPENCODE      APP_OPENING.APP_OPENCODE%TYPE;

    -- 모집 목표 인원
    V_MEMBER_NUMBER     APP_OPENING.MEMBER_NUMBER%TYPE;
    
    -- 현재까지 모집 완료된 인원
    V_PERSONNEL         APP_OPENING.MEMBER_NUMBER%TYPE;
    
    -- 모집 종료일
    V_APP_ENDDATE       APP_OPENING.APP_ENDDATE%TYPE;
    
    
    -- 커서 선언 『개설신청 코드 커서』
    CURSOR OPENCODE_SELECT
    IS
    SELECT APP_OPENCODE
    FROM APP_OPENING
    WHERE TO_CHAR(APP_STARTDATE-1, 'YYYY-MM-DD')
          = TO_CHAR(SYSDATE, 'YYYY-MM-DD');
    --    ★──────────────────
    --      『프로젝트 시작일 하루 전(모집 종료일)이 현재 날짜(SYSDATE)』인
    --      개설 신청글의 개설 신청 코드를 받아온다.
    
BEGIN
    
    -- q(?▽?q)~ ☆* o(?▽?)o (づ ̄ 3 ̄)づ
    --====================================================================
    --===[커서를 통해, 오늘이 모집 종료일인 개설신청 코드를 받아온다.]
    --====================================================================

    OPEN OPENCODE_SELECT;
    

    LOOP
        FETCH OPENCODE_SELECT INTO V_APP_OPENCODE;
        
        EXIT WHEN OPENCODE_SELECT%NOTFOUND;
        
        --============================================
        -- [다음번 프로젝트 개설 확정 코드 구하기]
        --============================================
        SELECT NVL(MAX(CP_CODE), 0) + 1 INTO V_CP_CODE
        FROM C_PROJECT;
        
        --================================================
        -- 1. 특정 개설신청 글의 현재 모집 인원수 구하기
        --================================================
        SELECT COUNT(*) INTO V_PERSONNEL
        FROM APP_OPENING AO
             INNER JOIN ROLE_COMPOSITION RC
             ON AO.APP_OPENCODE = RC.APP_OPENCODE
             INNER JOIN MEMBER_APPLY MA
             ON RC.RC_CODE = MA.RC_CODE
             INNER JOIN A_RESULT AR
             ON MA.AR_CODE = AR.AR_CODE
        WHERE AO.APP_OPENCODE = V_APP_OPENCODE
              AND AR.AR_CODE = 1;
                  -- 멤버 지원이 성공한 경우에만 인원수 반영
                  
        --================================================
        -- 2. 목표 모집 인원수 구하기
        --================================================
        SELECT MEMBER_NUMBER INTO V_MEMBER_NUMBER
        FROM APP_OPENING
        WHERE APP_OPENCODE = V_APP_OPENCODE;
    
        --=================================================================
        -- 3. 현재 인원이 목표 모집 인원수가 같을 때 테이블에 INSERT 처리.
        --=================================================================
        IF (V_PERSONNEL = V_MEMBER_NUMBER)
        --  ===========   ==============
        --      ⓐ              ⓑ
        --*******************************************
        --  【ⓐ : 현재까지 모집 완료한 인원수】
        --  【ⓑ : 프로젝트 목표 모집 인원수】
        --*******************************************
            THEN
            INSERT INTO C_PROJECT (CP_CODE, CP_DATE, APP_OPENCODE)
            VALUES(V_CP_CODE, SYSDATE, V_APP_OPENCODE);
            
            COMMIT;
        ELSE
            DBMS_OUTPUT.PUT_LINE('[※프로젝트 목표 모집 인원이 채워지지 않았습니다.※]');
        END IF;
        
        
    END LOOP;
    
    CLOSE OPENCODE_SELECT;
    
    
    EXCEPTION
            WHEN OTHERS THEN ROLLBACK;

END;


--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩『프로시저 실행』▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

EXECUTE C_PROJECT_PRC;

--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩


--=============================================================
--========================[세션 변경]==========================
--=============================================================
--○ 날짜 시간 관련 세션 설정 변경
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
--==>> Session이(가) 변경되었습니다.

--○ 테스트(확인)
SELECT TRUNC(SYSDATE)+ 12/24
FROM DUAL;
--=============================================================



--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩『스케줄러 잡 등록』▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

BEGIN
    DBMS_SCHEDULER.CREATE_SCHEDULE
    ( SCHEDULE_NAME     => 'PJ_CONFIRM_SCHEDULE'
    , START_DATE        => TO_DATE('2024-02-18 14:00:00', 'YYYY-MM-DD HH24:MI:SS')
    --『START_DATE』     : 2024-02-18 일자의 오후 2시마다, 
    --                      모집인원이 채워진 개설신청글을 개설 확정 테이블로 이동한다.
    , END_DATE          => NULL
    , REPEAT_INTERVAL   => 'FREQ=DAILY; INTERVAL=1'
    --『REPEAT_INTERVAL』: 매일 오후 2시마다, 개설 확정 테이블을 업데이트한다.
    );
END;

--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩



--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩▩『프로그램 등록』▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

BEGIN 
    DBMS_SCHEDULER.CREATE_PROGRAM
    ( PROGRAM_NAME => 'PJ_CONFIRM_PRG'
    , PROGRAM_ACTION => 'C_PROJECT_PRC'
    , PROGRAM_TYPE => 'STORED_PROCEDURE'
    , ENABLED => TRUE
    );
END;

--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩



--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩▩▩▩『잡 등록』▩▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

BEGIN
    DBMS_SCHEDULER.CREATE_JOB
    ( JOB_NAME => 'PJ_CONFIRM_JOB'
    , PROGRAM_NAME => 'PJ_CONFIRM_PRG'
    , SCHEDULE_NAME => 'PJ_CONFIRM_SCHEDULE'
    , ENABLED => TRUE
    );
END;

--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩


--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

--=================================
-- [스케줄러 잡 동작 결과 확인.]
--=================================
SELECT *
FROM USER_SCHEDULER_JOB_RUN_DETAILS
WHERE JOB_NAME = 'PJ_CONFIRM_JOB';
--=================================

--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩


--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩[ 추가 설명 ]▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩
--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩

-- 데이터 딕셔너리는 사용자가 사용하는 것이 아니라, 보는 것만(view) 가능하다.
-- 실제로 데이터 딕셔너리를 이용하는 것은 오라클이다.
-- ★ 따라서, 『JOB 에 대한 기록은 사용자가 직접 수정하거나 삭제하거나 변경하는 것은 안 된다.』
--            ================================================================================

-- 오라클 내부 객체를 다른 곳에서도 사용할 수 있도록 하려면, 다른 이름으로도 접근 할 수 있도록 해야한다.
-- 그것이 『시노님(Synonym)』 이다.
-- 어떤 계층을 가지고 있는 사용자냐에 따라서 시노님(Synonym)이 달라진다.


-- [프로그램 생성 과정에서 PL/SQL 처리가 가능한가]
-- 프로그램, 잡, 스케줄러를 묶어 쓰는 과정에서는 PL/SQL을 사용했었다.
-- 프로그램에 대한 타입도 PL/SQL, STORED_PROCEDUER 사용이 가능하다.

-- 기존에 만들어진 SCHEDULER 에 JOB 을 끼워쓸 수 있도록 한 것!
-- 속성이 20개 정도가 존재한다.
-- 미리 예약어처럼 만들어 두고, 서비스 지원을 하지 않는 것이 절반 이상이다.

-- 하나의 프로시저를 하나의 프로그램에 등록해서 사용하면 된다.
-- 하나의 프로그램에 프로시저를 추가하려고 하면 현재는 에러가 발생한다.
-- 추후에는, 프로그램 하나에 두 개 이상의 프로시저를 등록할 수 있게 된다.

-- 프로그램 & 잡 → 스케줄러 연결과 같은 방식으로 사용 중이다.
-- JOB 이 중간에 연결되도록 해 주는 것이다.

--▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩▩



SELECT ('CP' || (NVL(MAX(CP_CODE), 0) + 1)) AS CP_CODE
FROM C_PROJECT;

SELECT *
FROM C_PROJECT;

INSERT INTO C_PROJECT(CP_CODE, CP_DATE, APP_OPENCODE)
VALUES 
( (SELECT ('CP' || (NVL(MAX(CP_CODE), 0) + 1)) 
   FROM C_PROJECT)
   , SYSDATE, 4 );