Notice
Recent Posts
Recent Comments
Link
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

Everything has an expiration date

[Oracle - PL/SQL] 20231106 [프로그램 소스] 본문

[Oracle]/PL·SQL (Program source)

[Oracle - PL/SQL] 20231106 [프로그램 소스]

Jelly-fish 2023. 11. 6. 17:40

 

20231106_01_scott(plsql).sql
SELECT USER
FROM DUAL;
--==>> SCOTT



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

/*
실행 예)
EXEC PRC_STUDENT_UPDATE('moon', 'java000', '010-9999-9999', '강원도 횡성');
--==>> 데이터 수정 Ⅹ

EXEC PRC_STUDENT_UPDATE('moon', 'java006$', '010-9999-9999', '강원도 횡성');
--==>> 데이터 수정 ○

*/



SELECT *
FROM TBL_STUDENTS;
--==>>
/*
ID	    NAME	    TEL	            ADDR
moon	    문정환	010-9999-9999	강원도 횡성
wool	정한울	010-2222-2222	서울 강남구
*/


SELECT *
FROM TBL_IDPW;
--==>>
/*
ID	    PW
moon    	java006$
wool	java006$
*/



CREATE OR REPLACE PROCEDURE PRC_STUDENT_UPDATE2
( 아이디
, 패스워드
, 전화번호
, 주소
)
IS
BEGIN
END;



-- 두 개의 테이블은 부모 자식 관계가 아니라 1대1 관계이므로
-- 어떤 테이블에서 ID를 가져오는지는 상관이 없다.

-- 방법 1.



CREATE OR REPLACE PROCEDURE PRC_STUDENT_UPDATE2
( V_ID      IN TBL_IDPW.ID%TYPE
, V_PW      IN TBL_IDPW.ID%TYPE     -- STUDENTS 테이블에 존재하지 않는다.
, V_TEL     IN TBL_STUDENTS.TEL%TYPE
, V_ADDR    IN TBL_STUDENTS.ADDR%TYPE
)
IS
    V_PW2       TBL_IDPW.PW%TYPE;
    
-- 사용자가 실제로 입력한 값 : V_PW
-- 사용자가 입력한 값과 실제로 비교해야할 원래의 PW : V_PW2


-- 입력한 패스워드와, 실제 패스워드가 맞는지를 확인할 FLAG 변수.
-- 오라클에서는 boolean 타입이 없으므로, NUMBER로 구성.
-- 임의의 값을 우선 담아둔다.

    V_FLAG      NUMBER := 0;        -- 패스워드일치 : 1 / 패스워드불일치 : 2

BEGIN

    -- * 이렇게 구한 결과값을 변수에 담아둬야, 나중에 비교할 대상으로 사용 가능하다.
    
    SELECT PW  INTO V_PW2
    FROM TBL_IDPW
    WHERE ID = V_ID;
    
    
    IF (V_PW = V_PW2)           -- 패스워드 일치
        THEN V_FLAG := 1;
        
    ELSE 
        V_FLAG := 2;            -- 패스워드 불일치
        
    END IF;
    
    -- V_FLAG 가 2 이면, WHERE의 두 번째 조건 (V_FLAG = 1)이 참이 아니므로
    -- 업데이트가 발생하지 않는다.
    
    UPDATE TBL_STUDENTS
    SET TEL = V_TEL, ADDR = V_ADDR
    WHERE ID = V_ID
      AND V_FLAG = 1;

    COMMIT;

END;

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






-- 방법 2.

CREATE OR REPLACE PROCEDURE PRC_STUDENT_UPDATE3
( V_ID      IN TBL_IDPW.ID%TYPE
, V_PW      IN TBL_IDPW.ID%TYPE  
, V_TEL     IN TBL_STUDENTS.TEL%TYPE
, V_ADDR    IN TBL_STUDENTS.ADDR%TYPE
)
IS
BEGIN
    UPDATE (
                SELECT T1.ID, T1.PW, T2.TEL, T2.ADDR
                FROM TBL_IDPW T1 JOIN TBL_STUDENTS T2
                ON T1.ID = T2.ID
            ) T
    SET T.TEL = V_TEL, T.ADDR = V_ADDR
    WHERE T.ID = V_ID
      AND T.PW = V_PW;
    
    
    COMMIT;

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







--○ TBL_INSA 테이블을 대상으로 신규 데이터 입력 프로시저를 작성한다.
--   NUM, NAME, SSN, IBSADATE, CITY, TEL, BUSEO, JIKWI, BASICPAY, SUDANG 으로 구성된 컬럼 중
--   NUM(사원번호) 항목을 제외한 데이터 입력 시
--   해당 항목의 값은 기존 부여된 사원 번호의 마지막 번호 그 다음 번호를
--   자동으로 입력 처리할 수 있는 프로시저로 구성한다.
--   프로시저명 : PRC_INSA_INSERT()
/*
실행 예)
EXEC PRC_INSA_INSERT('최혜인', '970812-2234567', SYSDATE, '서울', '010-2509-1783'
                    , '개발부', '대리', 2000000, 2000000);   -- 이백만, 이백만 

→ 위와 같이 프로시저 호출 및 실행


1061 최혜인 970812-2234567 2023-11-06  서울 010-2509-1783 개발부 대리 2000000 2000000
의 데이터가 신규 입력된 상황


*/





CREATE OR REPLACE PROCEDURE PRC_INSA_INSERT
( V_NAME        TBL_INSA.NAME%TYPE
, V_SSN         TBL_INSA.SSN%TYPE
, V_IBSADATE    TBL_INSA.IBSADATE%TYPE
, V_CITY        TBL_INSA.CITY%TYPE
, V_TEL         TBL_INSA.TEL%TYPE
, V_BUSEO       TBL_INSA.BUSEO%TYPE
, V_JIKWI       TBL_INSA.JIKWI%TYPE
, V_BASICPAY    TBL_INSA.BASICPAY%TYPE
, V_SUDANG      TBL_INSA.SUDANG%TYPE
)
IS
    V_NUM       TBL_INSA.NUM%TYPE;
BEGIN

    -- #1 V_NUM에 마지막 사원번호 + 1의 값을 대입해 준다.
    
    SELECT (MAX(NUM) + 1) INTO V_NUM
    FROM TBL_INSA;
    
    
    -- #2 입력받은 매개변수와, V_NUM을 대입하여
    --    TBL_INSA 테이블에 새로운 데이터를 입력해 준다.
    
    
    INSERT INTO TBL_INSA(NUM, NAME, SSN, IBSADATE, CITY, TEL, BUSEO, JIKWI, BASICPAY, SUDANG)
    VALUES(V_NUM, V_NAME, V_SSN, V_IBSADATE, V_CITY, V_TEL, V_BUSEO, V_JIKWI, V_BASICPAY, V_SUDANG);
    
    COMMIT;
    
END;
--==>> Procedure PRC_INSA_INSERT이(가) 컴파일되었습니다.







--[선생님 풀이!!!]

CREATE OR REPLACE PROCEDURE PRC_INSA_INSERT2
( V_NAME        TBL_INSA.NAME%TYPE
, V_SSN         TBL_INSA.SSN%TYPE
, V_IBSADATE    TBL_INSA.IBSADATE%TYPE
, V_CITY        TBL_INSA.CITY%TYPE
, V_TEL         TBL_INSA.TEL%TYPE
, V_BUSEO       TBL_INSA.BUSEO%TYPE
, V_JIKWI       TBL_INSA.JIKWI%TYPE
, V_BASICPAY    TBL_INSA.BASICPAY%TYPE
, V_SUDANG      TBL_INSA.SUDANG%TYPE
)
IS
    V_NUM       TBL_INSA.NUM%TYPE;
BEGIN

    --★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    -- NUM 값을 얻어냈을 때, 만약 NULL 값이라면...(레코드가 아무것도 들어가있지 않다면!!)
    -- 사원번호가 계속해서 NULL로 처리되므로 이를 0으로 처리하라는 것을 명령해야 한다.
    --★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

    -- 기존 부여된 사원번호의 마지막 번호
    SELECT MAX(NVL(NUM, 0)) INTO V_NUM
    FROM TBL_INSA;

    INSERT INTO TBL_INSA(NUM, NAME, SSN, IBSADATE, CITY, TEL, BUSEO, JIKWI, BASICPAY, SUDANG)
    VALUES(V_NUM + 1, V_NAME, V_SSN, V_IBSADATE, V_CITY, V_TEL, V_BUSEO, V_JIKWI, V_BASICPAY, V_SUDANG);
    
    -- 커밋
    COMMIT;
    
    
    /*
    SELECT MAX(NVL(NUM, 0)) + 1 INTO V_NUM
    FROM TBL_INSA;

    INSERT INTO TBL_INSA(NUM, NAME, SSN, IBSADATE, CITY, TEL, BUSEO, JIKWI, BASICPAY, SUDANG)
    VALUES(V_NUM, V_NAME, V_SSN, V_IBSADATE, V_CITY, V_TEL, V_BUSEO, V_JIKWI, V_BASICPAY, V_SUDANG);
    
    COMMIT;
    */
    
END;
--==>> Procedure PRC_INSA_INSERT2이(가) 컴파일되었습니다.




-- [이 구문이 불가능한 이유.(에러 발생!)]***************************************
--V_NUM := (SELECT NAME

--          FROM TBL_INSA
--          WHERE NUM=1001);
--          
--          동일한 메모리 영역이라면 값을 담을 수 있을텐데 서로 다르다.
--          PLSQL 변수 선언 메모리 구조랑
--          쿼리문을 통해 값을 얻어내는 메모리 구조랑 다르다.

-- 따라서, INTO 를 통해 값을 담아내야 한다.
--****************************************************************************
          





--※ 20231106_02_scott.sql 파일을 참조하여
--   TBL_상품, TBL_입고 테이블을 대상으로
--   TBL_입고 테이블에 데이터 입력 시(즉, 입고 이벤트 발생 시)
--   TBL_상품 테이블의 해당 상품에 대한 재고수량이 함ㄲ 변동될 수 있는 기능을 가진
--   프로시저를 작성한다.
--   단, 이 과정에서 입고 번호는 자동 증가 처리한다. (시퀀스 사용 안함)
--   TBL_입고 테이블 구성 컬럼은
--   입고번호, 상품코드, 입고일자, 입고수량, 입고단가이며
--   프로시저 호출을 통해 전달할 파라미터는 상품코드, 입고수량, 입고단가이다.
--   프로시저명 : PRC_입고_INSERT(상품코드, 입고수량, 입고단가)


DESC TBL_입고;

CREATE OR REPLACE PROCEDURE PRC_입고_INSERT
( V_상품코드    TBL_입고.상품코드%TYPE
, V_입고수량    TBL_입고.입고수량%TYPE
, V_입고단가    TBL_입고.입고단가%TYPE
)
IS
    
    V_입고번호  TBL_입고.입고번호%TYPE;
    

BEGIN
    
-- ① INSERT → TBL_입고
--    INSERT INTO TBL_입고(입고번호, 상품코드, 입고일자, 입고수량, 입고단가)
--    VALUES(1, 'H001', SYSDATE, 30, 400);

    SELECT NVL(MAX(입고번호), 0) + 1 INTO V_입고번호
    FROM TBL_입고;

    
    INSERT INTO TBL_입고(입고번호, 상품코드, 입고일자, 입고수량, 입고단가)
    VALUES(V_입고번호, V_상품코드, SYSDATE, V_입고수량, V_입고단가);
    


-- ② UPDATE → TBL_상품
--    UPDATE TBL_상품
--    SET 재고수량 = 기존재고수량 + 입고수량      -- CHECK~!!!
--    WHERE 상품코드 = 'H001';

    
    UPDATE TBL_상품 TS
    SET TS.재고수량 = TS.재고수량 + V_입고수량
    WHERE TS.상품코드 = V_상품코드;
    
    COMMIT;

END;
--==>> Procedure PRC_입고_INSERT이(가) 컴파일되었습니다.




--[선생님 풀이!!!]

CREATE OR REPLACE PROCEDURE PRC_입고_INSERT2
( V_상품코드    TBL_상품.상품코드%TYPE
, V_입고수량    TBL_입고.입고수량%TYPE
, V_입고단가    TBL_입고.입고단가%TYPE
)
IS
    -- 선언부
    -- 아래의 쿼리문을 수행하기 위해 필요한 변수 추가 선언
    V_입고번호  TBL_입고.입고번호%TYPE;
    
BEGIN
    -- 실행부
    -- 선언한 변수에 값 담아내기
    -- SELECT 쿼리문 수행 → 입고번호 확인
    SELECT NVL(MAX(입고번호), 0) INTO V_입고번호
    FROM TBL_입고;
    -- 레코드가 있는 상태에서...

    
    SELECT MAX(NVL(입고번호, 1))
    FROM TBL_입고;
    --==>> (NULL)
    --**************************************************************************
    -- 레코드 자체가 없는 데에서 가져오니까
    -- NULL이 반환이 안 되는 것이다.
    -- 만약 레코드가 존재하는데, 입고번호가 NULL이었다면 NVL이 제대로 실행되었겠지만
    -- 현재 레코드가 존재하지 않는 상태이므로...
    --**************************************************************************

    
    -- INSERT 쿼리문 수행
    INSERT INTO TBL_입고 (입고번호, 상품코드, 입고수량, 입고단가)
    VALUES ((V_입고번호 + 1), V_상품코드, V_입고수량, V_입고단가);
    
    
    -- UPDATE 쿼리문 수행
    -- 논리적으로, 입고수량 테이블에 레코드가 추가되어야 UPDATE TBL_상품 을 할 수 있으므로
    -- INSERT INTO 이후에 UPDATE를 한 것이다.
    
    UPDATE TBL_상품
    SET 재고수량 = 재고수량 + V_입고수량
    WHERE 상품코드 = V_상품코드;
    
    -- 커밋
    
    
    -- 예외 처리
    EXCEPTION
        -- 코드레벨에서 명시한 상황이 아닌 다른 상황이 발생하게 되면...
        -- THEN 롤백해라!!
        WHEN OTHERS THEN ROLLBACK;
        -- 기존 상황이 아닌 상황이 발생했을 경우 모두 ROLLBACK!
        -- 그 어떠한 것도 반영하지 않는다.
        
    
    
    COMMIT;
    
    
END;
--==>> Procedure PRC_입고_INSERT2이(가) 컴파일되었습니다.







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

--★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
--★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
--★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
--★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★


-- ★ [이 문제를 통해 선생님이 전달하고 싶었던 것...]

/*

        혜성                      윤수
     
        농협                      신한
     
  1,200,000 → 200,000             0
 
                                1,000,000 (데이트비 하라구 100만 원 빌려줌...)
     
        
        
    UPDATE 고객계좌                 UPDATE 고객계좌
    SET 잔액 = 200000               SET 잔액 = 1000000
    WHERE 예금주코드 = 혜성          WHERE 예금주코드 = 윤수


만약, 혜성이가 100만 원을 입금할 때 전산장애가 발생해서
윤수한테 100만 원이 전해지지 않고, 혜성이는 20만 원만 남는다?

둘 중에 하나만 실행된다면 위와 같은 문제가 발생할 것이다.
하지만, 트랜잭션은 한번에 실행 되거나 실행되지 않거나 둘 중 하나이기 때문에
(ALL OR NOTHING)!!!!!!!!!!!!!

트랜잭션의 특징
ⓐ 【원자성(ATOMICITY)】
트랜잭션에서 정의된 연산들은
모두 성공하거나, 모두 실행되지 않거나 둘 중 하나이다.
ALL OR NOTHING!!!!!!!!!!!!!!!



둘 중에 어느 하나라도 문제가 생기면 ROLLBACK을 한다!!
그렇기에 위와 같은 문제가 발생하지 않는다.

혜성 = 빨강 동그라미
윤수 = 파랑 동그라미

빨강 동그라미, 파랑 동그라미가 모두 성공했을 때 = COMMIT!
둘 중 하나라도 실패 = ROLLBACK!

★이러한 처리를 [트랜잭션 처리]라고 한다.

일부만 실행 : 롤백
모두 실행 완료 : COMMIT!!


TCL 구문(TRANSACTION CONTROL LANGUAGE) : COMMIT, ROLLBACK!!!


입고수량 입력을 했는데 재고수량이 변경되지 않으면 = 무결성이 깨진다!!
두 개가 모두 실행됐을 때 커밋이 되어야 한다.
둘 중에 하나만 실행 됐을 때는 커밋 금지!!!

둘 중에 하나만 실행 됐을 때 ROLLBACK!!!!
*/





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


--■■■ 프로시저 내에서의 예외 처리 ■■■--


--○ TBL_MEMBER 테이블에 데이터를 입력하는 프로시저를 작성
--   단, 이 프로시저를 통해 데이터를 입력할 경우
--   CITY(지역) 항목에 '서울', '경기', '대전'만 입력이 가능하도록 구성한다.
--   이 지역 외의 다른 지역을 프로시저 호출을 통해 입력하려는 경우
--   (즉, 유효하지 않은 데이터 입력을 시도하려는 경우)
--   예외에 대한 처리를 하려고 한다.
--   프로시저명 : PRC_MEMBER_INSERT()
/*
실행 예)
EXEC PRC_MEMBER_INSERT('박범구', '010-1111-1111', '서울');
--> 데이터 입력 ○

EXEC PRC_MEMBER_INSERT('김경태', '010-2222-2222', '부산');
--> 데이터 입력 Ⅹ
*/


CREATE OR REPLACE PROCEDURE PRC_MEMBER_INSERT
( V_NAME    IN TBL_MEMBER.NAME%TYPE
, V_TEL     IN TBL_MEMBER.TEL%TYPE
, V_CITY    IN TBL_MEMBER.CITY%TYPE
)
IS
    -- 실행 영역의 쿼리문 수행을 위해 필요한 변수 선언
    V_NUM   TBL_MEMBER.NUM%TYPE;
    
    -- 사용자 정의 예외를 변수처럼 선언하여, IF문에서 처리하자.
    -- USER_DEFINE_ERROR는 '예외타입'이다.
    
    
    -- 사용자 정의 예외에 대한 변수 선언 CHECK~!!!
    USER_DEFINE_ERROR   EXCEPTION;
BEGIN
    
    -- 프로시저를 통해 입력 처리를 정상적으로 진행해야 할 데이터인지 아닌지의 여부를
    -- 가장 먼저 확인할 수 있도록 코드 구성
    
    
    -- 매개변수로 입력받은 값이, 서울, 경기, 대전 중 어느 하나도 아닐 경우.
    IF (V_CITY NOT IN ('서울', '경기', '대전'))
        -- 예외 발생    CHECK~!!!
        -- *[RAISE] : 일으키다, 발생시키다.
        -- 서울, 경기, 대전이 아닐 경우 USER_DEFINE_ERROR를 발생시킬 것이다.
        -- 예외를 일으키는 구문은 항상 COMMIT보다 먼저 작성하자.
        
        
        THEN RAISE USER_DEFINE_ERROR;
        
    END IF;
    
    
    
    -- 선언한 변수에 값 담아내기
    SELECT NVL(MAX(NUM), 0) INTO V_NUM
    FROM TBL_MEMBER;
    
    
    -- 쿼리문 구성 → INSERT
    INSERT INTO TBL_MEMBER(NUM, NAME, TEL, CITY)
    VALUES(V_NUM + 1, V_NAME, V_TEL, V_CITY);
    
    -- 예외 처리 구문
    -- 오류가, USER_DEFINE_ERROR라면...
    -- 오라클 내장 에러 함수를 호출한다.
    -- 2만 1번부터 유저가 부여할 수 있는 에러 번호이다.
    
    -- [JAVA]의 TRY~CATCH 와 유사함.
    
    EXCEPTION
        WHEN USER_DEFINE_ERROR
            THEN RAISE_APPLICATION_ERROR(-20001, '서울, 경기, 대전만 입력이 가능합니다.');
                ROLLBACK;
                -- 잘못된 데이터를 입력했으므로, 롤백한다!
        
        -- 우리가 규정한 에러 : USER_DEFINE_ERROR가 아닌 것이 발생할 수도 있다!
        -- 기타 다른 예외가 발생하면...
        WHEN OTHERS 
            THEN ROLLBACK;  -- 롤백만 해라~!!
            
        -- 사용자 정의 예외를 여러 개 지정해서
        -- 각 에러의 경우에 따라 다른 안내 메시지가 출력되도록 처리할 수도 있겠다.
        

    -- 커밋
    COMMIT;
    
END;
--==>> Procedure PRC_MEMBER_INSERT이(가) 컴파일되었습니다.


DESC TBL_출고;


--○ TBL_출고 테이블에 데이터 입력 시 (즉, 출고 이벤트 발생 시)
--   TBL_상품 테이블의 재고수량이 변동되는 프로시저를 작성한다.
--   단, 출고번호는 입고번호와 마찬가지로 자동 증가,
--   또한, 출고수량이 재고수량보다 많은 경우...
--   출고 액션을 취소할 수 있도록 처리한다.
--   (출고가 이루어지지 않도록...) → 예외 처리 활용 CHECK~!!!
--   프로시저명 : PRC_출고_INSERT()
/*
실행 예)
EXEC PRC_출고_INSERT('H001', 10, 600);

→ 이 시점에서의 상품 테이블의 바밤바 재고수량은 70개

EXEC PRC_출고_INSERT('H001', 80, 600);

→ 에러 발생
-- (20002, 재고 부족~!!!)

*/

/*

이름   널?       유형           
---- -------- ------------ 
출고번호 NOT NULL NUMBER       
상품코드          VARCHAR2(20) 
출고일자          DATE         
출고수량          NUMBER       
출고단가          NUMBER 
*/


CREATE OR REPLACE PROCEDURE PRC_출고_INSERT
( V_상품코드    IN TBL_출고.상품코드%TYPE
, V_출고수량    IN TBL_출고.출고수량%TYPE
, V_출고단가    IN TBL_출고.출고단가%TYPE
)
IS
    
    V_출고번호  TBL_출고.출고번호%TYPE;
    V_재고수량  TBL_상품.재고수량%TYPE;
    USER_DEFINE_ERROR2   EXCEPTION;

BEGIN

    -- #1 출고번호 연산
    
    SELECT NVL(MAX(출고번호), 0) + 1 INTO V_출고번호
    FROM TBL_출고;
    
    -- #2 TBL_출고 테이블에 입력.
    
    INSERT INTO TBL_출고(출고번호, 상품코드, 출고수량, 출고단가)
    VALUES(V_출고번호, V_상품코드, V_출고수량, V_출고단가);
    
    
    
    SELECT 재고수량 INTO V_재고수량
    FROM TBL_상품
    WHERE 상품코드 = V_상품코드;
            
    
    -- #5 EXCEPTION 정의
    
    -- 입력받은 출고수량이, 상품의 재고수량보다 클 때 EXCEPTION 발생
    
    IF (V_출고수량 > V_재고수량)

        THEN RAISE  USER_DEFINE_ERROR2;
        
    END IF;
    
    
    -- #3 출고 테이블의 수량과 상품코드에 맞게 수량을 제거.
    
    UPDATE TBL_상품
    SET 재고수량 = 재고수량 - V_출고수량
    WHERE 상품코드 = V_상품코드;
    
    
    EXCEPTION
        WHEN USER_DEFINE_ERROR2
            THEN RAISE_APPLICATION_ERROR(-20002, '재고 부족~!!!');
                ROLLBACK;
        
        WHEN OTHERS
            THEN ROLLBACK;
    
    
    -- #4 커밋
     COMMIT;


END;



--[선생님 풀이!!!]



CREATE OR REPLACE PROCEDURE PRC_출고_INSERT2
( V_상품코드    IN TBL_상품.상품코드%TYPE
, V_출고수량    IN TBL_출고.출고수량%TYPE
, V_출고단가    IN TBL_출고.출고단가%TYPE
)
IS
    -- 주요 변수 선언
    V_출고번호  TBL_출고.출고번호%TYPE;
    V_재고수량  TBL_상품.재고수량%TYPE;
    
    -- 사용자 정의 예외 선언
    USER_DEFINE_ERROR   EXCEPTION;
    
BEGIN
    
    -- 쿼리문 수행 이전에 수행 여부를 확인하는 과정에서
    -- 재고수량 파악 → 기존 재고를 확인하는 과정이 선행되어야 한다.
    -- 그래야 프로시저 호출 시 넘겨받는 출고수량과 비교가 가능하기 때문...
    
    SELECT 재고수량 INTO V_재고수량
    FROM TBL_상품
    WHERE 상품코드 = V_상품코드;
    
    -- 출고를 정상적으로 진행해줄 것인지에 대한 여부 확인
    -- 위에서 파악한 재고수량보다 현재 프로시저에서 넘겨받은 출고수량이 많으면
    -- 예외 발생~!!!
    IF (V_출고수량 > V_재고수량)
        -- 예외 발생
        THEN RAISE USER_DEFINE_ERROR;
    END IF;
    
    
    -- 출고번호 얻어내기 → 위에서 선언한 변수에 값 담아내기
    
    SELECT NVL(MAX(출고번호), 0) + 1 INTO V_출고번호
    FROM TBL_출고;
    

    -- 쿼리문 구성 → INSERT(TBL_출고)
    INSERT INTO TBL_출고(출고번호, 상품코드, 출고수량, 출고단가)
    VALUES(V_출고번호, V_상품코드, V_출고수량, V_출고단가);
    
    -- 쿼리문 구성 → UPDATE(TBL_상품)
    UPDATE TBL_상품
    SET 재고수량 = 재고수량 - V_출고수량
    WHERE 상품코드 = V_상품코드;
    
    
    -- 항상 예외 처리는 커밋 위에서 수행하기로 하자.
    
    
    -- JAVA에서의 TRY~CATCH처럼 처리하자.
    
    --예외 처리
    EXCEPTION
        WHEN USER_DEFINE_ERROR
            THEN RAISE_APPLICATION_ERROR(-20002, '재고 부족~!!!');
                 ROLLBACK;
        WHEN OTHERS
            THEN ROLLBACK;
    
    
    
    -- 커밋
    COMMIT;
    
    
END;
--==>> Procedure PRC_출고_INSERT2이(가) 컴파일되었습니다.


-- EXCEPTION 변수 선언 (USER_DEFINE_ERROR2)
-- IF (예외처리할 상황이 되면)
-- THEN RAISE (EXCEPTION 변수명)
-- END IF;

-- EXCEPTION 이 발생했을 때 할 처리.

-- EXCEPTION
--      WHEN (사용자정의 EXCEPTION?)
--          THEN RAISE_APPLICATION_ERROR(에러번호(20000부터...), '안내메시지');




--○ TBL_출고 테이블에서 출고수량을 수정(변경)하는 프로시저를 작성한다.
--   프로시저명 : PRC_출고_UPDATE()
/*
실행 예)
EXEC PRC_출고_UPDATE(출고번호, 변경할수량);
*/

-- 잘못 들어갔던 출고수량을 다시 더해주고, 그 결과값에서 변경할 수량을 빼 준다.
-- 20 -> 50 가능
-- 20 -> 60 불가능(재고수량초과)
--********************************************************************
-- ① 잘못 들어갔던 출고 수량을 상품의 재고 수량에 더해준다.
-- ② 그 수량이 현재의 변경할 수량보다 작거나 같으면 : 변경 가능하다.
--                                            크면 : 변경이 불가능하다!!!!
--********************************************************************
                   
DESC TBL_출고;
DESC TBL_상품; 
                                            
CREATE OR REPLACE PROCEDURE PRC_출고_UPDATE
( V_출고번호        IN TBL_출고.출고번호%TYPE
, V_변경할수량      IN TBL_출고.출고수량%TYPE
)
IS
   -- # 출고번호에 맞는 상품 번호 저장
   V_상품코드          TBL_상품.상품코드%TYPE;
   
   
   -- # 변경하려는 출고 번호에 맞는 출고수량을 저장.
   V_변경전출고수량    TBL_출고.출고수량%TYPE;
   
   
   -- # 상품 번호에 맞는 재고수량 저장
   V_재고수량          TBL_상품.재고수량%TYPE;
   
   -- # 이전 출고수량을 다시 되돌려서 
   --   원래의 재고수량에 더했을 때의 값을 저장할 변수 지정.
   
   V_취소후재고수량    TBL_상품.재고수량%TYPE;
    
    
   -- # 사용자 정의 에러(EXCEPTION 정의)
   USER_DEFINE_ERROR3   EXCEPTION;

BEGIN

    -- #1 출고번호의 상품 코드를 확인.
    --    그 값을 변수에 저장.
    
    
    SELECT 상품코드 INTO V_상품코드
    FROM TBL_출고
    WHERE 출고번호 = V_출고번호;
    
    
    -- #2 출고번호에 맞는 변경전 출고 수량을 변수에 저장. 
    
    SELECT 출고수량 INTO V_변경전출고수량
    FROM TBL_출고
    WHERE 출고번호 = V_출고번호;
    
    
    -- #3 출고번호의 상품 코드와 일치하는 상품의 재고수량 확인
    
    SELECT 재고수량 INTO V_재고수량
    FROM TBL_상품
    WHERE 상품코드 = V_상품코드;
    
    
    --50 LINE
    
    -- #4 잘못 들어갔던 출고수량을 다시 더해준다.
    
    V_취소후재고수량 := V_재고수량 + V_변경전출고수량;
    

    
    -- #5 사용자가 매개변수로 입력한 V_변경할수량이
    --    위에서 연산한 취소후 재고수량보다 클 경우 에러를 발생시킨다.
    
    
    IF (V_변경할수량 > V_취소후재고수량)
        THEN RAISE USER_DEFINE_ERROR3;

    END IF;
    
    
    
    -- #5-1 EXCEPTION 이 발생하지 않았을 경우, 제대로 연산을 진행한다.
    
    -- ① 출고번호에 맞는 TBL_출고 테이블의 레코드를 변경할 수량에 맞게 업데이트한다.
    
    
    UPDATE TBL_출고
    SET 출고수량 = V_변경할수량
    WHERE 출고번호 = V_출고번호;
    
    
    -- ② 출고번호에 맞는 상품코드를 TBL_상품 테이블에서 조회하여
    --    재고를 취소한 수량만큼 증가시킨다.
    
    UPDATE TBL_상품
    SET 재고수량 = V_취소후재고수량 - V_변경할수량
    WHERE 상품코드 = V_상품코드;
    
    
    -- ③ 그 결과에서 V_변경할수량 만큼 감소시킨다.
    -- ④ ③의 값을 기반으로, TBL_상품의 테이블을 업데이트한다.
    
    
    
    -- #6 EXCEPTION 에 대한 처리를 진행한다.
    
    EXCEPTION
        WHEN USER_DEFINE_ERROR3
            THEN RAISE_APPLICATION_ERROR(-20003, '재고 부족~!!!');
            ROLLBACK;
        
        WHEN OTHERS
            THEN
            ROLLBACK;
            
    -- 모든 처리가 끝난 후에 COMMIT을 진행한다.
    
    COMMIT;
    
END;

 


 

20231106_02_scott.sql
SELECT USER
FROM DUAL;
--==>> SCOTT


--○ 프로시저 생성 후 실행 테스트 (잘못된 패스워드)


EXEC PRC_STUDENT_UPDATE2('moon', 'java000', '010-9999-9999', '강원도 횡성');
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.

--○프로시저 호출 후 테이블 조회

SELECT *
FROM TBL_STUDENTS;
--==>>
/*
ID	    NAME    	TEL	            ADDR
moon    	문정환	010-1111-1111	제주도 서귀포시    --> 데이터 변경되지 않았음~!!!
wool	정한울	010-2222-2222	서울 강남구
*/


--○ 프로시저 생성 후 실행 테스트 (올바른 패스워드)

EXEC PRC_STUDENT_UPDATE2('moon', 'java006$', '010-9999-9999', '강원도 횡성');
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.



--○프로시저 호출 후 테이블 조회

SELECT *
FROM TBL_STUDENTS;
--==>>
/*
ID	    NAME	    TEL	            ADDR
moon	    문정환	010-9999-9999	강원도 횡성
wool	정한울	010-2222-2222	서울 강남구
*/


--○ 프로시저 생성 후 실행 테스트 (잘못된 패스워드)


EXEC PRC_STUDENT_UPDATE2('wool', 'java000', '010-8888-8888', '전남 목포');
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.

--○프로시저 호출 후 테이블 조회

SELECT *
FROM TBL_STUDENTS;
--==>>
/*
ID	    NAME    	TEL	            ADDR
moon	    문정환	010-9999-9999	강원도 횡성
wool	정한울	010-2222-2222	서울 강남구
*/





--○ 프로시저 생성 후 실행 테스트 (올바른 패스워드)

EXEC PRC_STUDENT_UPDATE2('wool', 'java006$', '010-8888-8888', '전남 목포');
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.




--○프로시저 호출 후 테이블 조회

SELECT *
FROM TBL_STUDENTS;
--==>>
/*
ID  	NAME    	TEL	            ADDR
moon    	문정환	010-9999-9999	강원도 횡성
wool	정한울	010-8888-8888	전남 목포
*/



DESC TBL_INSA;
--==>>
/*
이름       널?       유형           
-------- -------- ------------ 
NUM      NOT NULL NUMBER(5)    
NAME     NOT NULL VARCHAR2(20) 
SSN      NOT NULL VARCHAR2(14) 
IBSADATE NOT NULL DATE         
CITY              VARCHAR2(10) 
TEL               VARCHAR2(15) 
BUSEO    NOT NULL VARCHAR2(15) 
JIKWI    NOT NULL VARCHAR2(15) 
BASICPAY NOT NULL NUMBER(10)   
SUDANG   NOT NULL NUMBER(10) 
*/



SELECT *
FROM TBL_INSA;



EXEC PRC_INSA_INSERT('최혜인', '970812-2234567', SYSDATE, '서울', '010-2509-1783', '개발부', '대리', 2000000, 2000000);


SELECT *
FROM TBL_INSA;



-- [선생님 프로시저!!!]

--※ 20231106_01_scott(plsql).sql 파일에서
--   PRC_INSA_INSERT() 프로시저 생성 후 테스트

-- 프로시저는 개행해서 실행하지 않는다. 한 줄로 실행하자!!

EXEC PRC_INSA_INSERT2('최혜인', '970812-2234567', SYSDATE, '서울', '010-2509-1783', '개발부', '대리', 2000000, 2000000);
--==> PL/SQL 프로시저가 성공적으로 완료되었습니다.


--○ 프로시저 호출(실행) 후 확인

SELECT *
FROM TBL_INSA;





--○ 실습 테이블 생성(TBL_상품)

CREATE TABLE TBL_상품
( 상품코드      VARCHAR2(20)
, 상품명        VARCHAR2(100)
, 소비자가격    NUMBER 
, 재고수량      NUMBER DEFAULT 0
, CONSTRAINT 상품_상품코드_PK PRIMARY KEY(상품코드)
);
--==>> Table TBL_상품이(가) 생성되었습니다.
-- TBL_상품 테이블의 상품코드 기본키(PK) 제약조건 설정



--○ 실습 테이블 생성(TBL_입고)

CREATE TABLE TBL_입고
( 입고번호  NUMBER
, 상품코드  VARCHAR2(20)
, 입고일자  DATE DEFAULT SYSDATE
, 입고수량  NUMBER
, 입고단가  NUMBER
, CONSTRAINT 입고_입고번호_PK PRIMARY KEY (입고번호)
, CONSTRAINT 입고_상품코드_FK FOREIGN KEY (상품코드)
            REFERENCES TBL_상품(상품코드)
);
--==>> Table TBL_입고이(가) 생성되었습니다.
-- TBL_입고 테이블의 입고번호를 기본키(PK) 제약조건 설정
-- TBL_입고 테이블의 상품코드는 TBL_상품 테이블의 상품코드를
-- 참조할수 있도록 외래키(FK) 제약조건 설정

--○ TBL_상품 테이블에 상품정보 입력
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('H001', '바밤바', 600);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('H002', '죠스바', 500);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('H003', '보석바', 500);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('H004', '누가바', 600);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('H005', '쌍쌍바', 700);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('H006', '수박바', 500);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('H007', '알껌바', 500);
--==>> 1 행 이(가) 삽입되었습니다. * 7



INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('C001', '빵빠레', 1600);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('C002', '월드콘', 1500);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('C003', '메타콘', 1500);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('C004', '구구콘', 1600);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('C005', '슈퍼콘', 1700);
--==>> 1 행 이(가) 삽입되었습니다. * 5


INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('E001', '빵또아', 2600);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('E002', '투게더', 2500);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('E003', '팥빙수', 2500);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('E004', '셀렉션', 2600);
INSERT INTO TBL_상품(상품코드, 상품명, 소비자가격) VALUES('E005', '설레임', 2700);


--○ 확인
SELECT *
FROM TBL_상품;
--==>>
/*
상품코드	상품명	소비자가격	재고수량
H001	바밤바	600	0
H002	죠스바	500	0
H003	보석바	500	0
H004	누가바	600	0
H005	쌍쌍바	700	0
H006	수박바	500	0
H007	알껌바	500	0
C001	빵빠레	1600	0
C002	월드콘	1500	0
C003	메타콘	1500	0
C004	구구콘	1600	0
C005	슈퍼콘	1700	0
E001	빵또아	2600	0
E002	투게더	2500	0
E003	팥빙수	2500	0
E004	셀렉션	2600	0
E005	설레임	2700	0
*/

--○ 커밋
COMMIT;
--==>> 커밋 완료


--○ 테이블 조회(입고내역 확인)

SELECT *
FROM TBL_입고;
--==>> 조회 결과 없음


--※ TBL_입고 테이블에 『입고』 이벤트 발생 시...
--   관련 테이블에 수행되어야 하는 내용

-- ① INSERT → TBL_입고
--    INSERT INTO TBL_입고(입고번호, 상품코드, 입고일자, 입고수량, 입고단가)
--    VALUES(1, 'H001', SYSDATE, 30, 400);

-- ② UPDATE → TBL_상품
--    UPDATE TBL_상품
--    SET 재고수량 = 기존재고수량 + 입고수량      -- CHECK~!!!
--    WHERE 상품코드 = 'H001';






--   프로시저명 : PRC_입고_INSERT(상품코드, 입고수량, 입고단가)
EXEC PRC_입고_INSERT('H001', 20, 400);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.



SELECT *
FROM TBL_상품;


--○ 생성한 프로시저가 제대로 작동하는지의 여부 확인 → 프로시저 호출
EXEC PRC_입고_INSERT(상품코드, 입고수량, 입고단가);


SELECT *
FROM TBL_입고;

EXEC PRC_입고_INSERT('H001', 30, 500);


SELECT *
FROM TBL_상품;
--==>>

/*
              :
    H001	    바밤바	600	    30
              :
*/

SELECT *
FROM TBL_입고;
--==>>
/*
입고번호	상품코드    	입고일자	    입고수량	    입고단가
1	    H001	        2023-11-06	30	        500
*/



EXEC PRC_입고_INSERT('H002', 20, 400);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.



SELECT *
FROM TBL_상품;
--==>>
/*
          :
H002	    죠스바	500	    20
          :
*/


SELECT *
FROM TBL_입고;
--==>>
/*
입고번호	상품코드	입고일자	입고수량	입고단가
1	H001	2023-11-06	30	500
2	H002	2023-11-06	20	400
*/



EXEC PRC_입고_INSERT('H001', 50, 500);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.


SELECT *
FROM TBL_상품;
--==>>
/*
H001    	바밤바	600	    80
*/

SELECT *
FROM TBL_입고;
--==>>
/*
입고번호	상품코드	    입고일자	    입고수량	입고단가
3	    H001	        2023-11-06      	50	    500
1	    H001        	2023-11-06	    30	    500
2	    H002	        2023-11-06      	20	    400

*/



EXEC PRC_입고_INSERT('H002', 30, 400);
EXEC PRC_입고_INSERT('H003', 35, 400);
EXEC PRC_입고_INSERT('H004', 70, 500);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다. * 3



EXEC PRC_입고_INSERT('C001', 26, 1400);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.

EXEC PRC_입고_INSERT('C001', 24, 1400);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.

EXEC PRC_입고_INSERT('C001', 20, 1500);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.

EXEC PRC_입고_INSERT('C002', 20, 1000);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.

EXEC PRC_입고_INSERT('C003', 20, 1000);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.

EXEC PRC_입고_INSERT('C004', 20, 1000);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.



SELECT *
FROM TBL_입고;
--==>>
/*
입고번호	상품코드    	입고일자	입고수량	입고단가
3	    H001    	    2023-11-06	50	500
4	    H002	        2023-11-06	30	400
1	    H001        	2023-11-06	30	500
2	    H002    	    2023-11-06	20	400
5	    H003        	2023-11-06	35	400
6	    H004	        2023-11-06	70	500
7	    C001	    2023-11-06	26	1400
8	    C001	    2023-11-06	24	1400
9	    C001	    2023-11-06	20	1500
10	    C002    	    2023-11-06	20	1000
11	    C003	    2023-11-06	20	1000
12	    C004	    2023-11-06	20	1000
*/


SELECT *
FROM TBL_상품;
--==>>
/*
상품코드	상품명	소비자가격	재고수량
H001	    바밤바	600     	80
H002	    죠스바	500	        50
H003	    보석바	500	        35
H004	    누가바	600	        70
H005	    쌍쌍바	700	        0
H006	    수박바	500	        0
H007	    알껌바	500	        0
C001	빵빠레	1600	    70
C002    	월드콘	1500	    20
C003	메타콘	1500	    20
C004	구구콘	1600	    20
C005	슈퍼콘	1700	    0
E001	빵또아	2600        	0
E002	    투게더	2500        	0
E003	팥빙수	2500        	0
E004	셀렉션	2600        	0
E005	설레임	2700	        .0
*/


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


--■■■ 프로시저 내에서의 예외 처리 ■■■--

--○ 실습 테이블 생성(TBL_MEMBER)

CREATE TABLE TBL_MEMBER
( NUM       NUMBER
, NAME      VARCHAR2(30)
, TEL       VARCHAR2(60)
, CITY      VARCHAR2(60)
, CONSTRAINT MEMBER_NUM_PK PRIMARY KEY (NUM)
);
--==>> Table TBL_MEMBER이(가) 생성되었습니다.

-- CITY에 입력할 수 있는 데이터는, 
-- 경기, 대전과 같은 특정 값만 입력이 가능하도록 하려고 하는 것.




--○ 생성한 프로시저가 제대로 작동하는지의 여부 확인

EXEC PRC_MEMBER_INSERT('박범구', '010-1111-1111', '서울');
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.


SELECT *
FROM TBL_MEMBER;
--==>> 
/*
NUM	NAME	TEL	CITY
1	박범구	010-1111-1111	서울
*/

EXEC PRC_MEMBER_INSERT('김경태', '010-2222-2222', '부산');
--==>> 에러 발생
-- ORA-20001 (아까 전에 사용자가 부여했던 에러 번호)
/*

명령의 448 행에서 시작하는 중 오류 발생 -
BEGIN PRC_MEMBER_INSERT('김경태', '010-2222-2222', '부산'); END;
오류 보고 -
ORA-20001: 서울, 경기, 대전만 입력이 가능합니다.
ORA-06512: at "SCOTT.PRC_MEMBER_INSERT", line 53
ORA-06512: at line 1

*/



SELECT *
FROM TBL_MEMBER;
--==>> 1	박범구	010-1111-1111	서울


DESC TBL_상품;

--○ 실습 테이블 생성(TBL_출고)
CREATE TABLE TBL_출고
( 출고번호  NUMBER
, 상품코드  VARCHAR2(20)
, 출고일자  DATE    DEFAULT SYSDATE
, 출고수량  NUMBER
, 출고단가  NUMBER
);
--==>> Table TBL_출고이(가) 생성되었습니다.



-- 출고번호 PK 지정

ALTER TABLE TBL_출고
ADD CONSTRAINT 출고_출고번호_PK PRIMARY KEY (출고번호);
--==>> Table TBL_출고이(가) 변경되었습니다.

SELECT *
FROM TBL_상품;

SELECT *
FROM USER_CONSTRAINTS
WHERE TABLE_NAME = 'TBL_상품';

-- 상품코드 FK 지정

ALTER TABLE TBL_출고
ADD CONSTRAINT 출고_상품코드_FK FOREIGN KEY (상품코드)
               REFERENCES TBL_상품(상품코드);
--==>> Table TBL_출고이(가) 변경되었습니다.


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


SELECT *
FROM TBL_상품;
--==>>
/*
상품코드	상품명	소비자가격	재고수량
H001	    바밤바	600     	80
H002    	죠스바	500	        50
H003    	보석바	500	        35
H004	    누가바	600	        70
H005	    쌍쌍바	700	        0
H006	    수박바	500	        0
H007	    알껌바	500	        0
C001	빵빠레	1600	    70
C002	    월드콘	1500	    20
C003	메타콘	1500	    20
C004	구구콘	1600	    20
C005	슈퍼콘	1700	    0
E001	빵또아	2600        	0
E002	    투게더	2500        	0
E003	팥빙수	2500        	0
E004	셀렉션	2600	        0
E005	설레임	2700	        0
*/

SELECT *
FROM TBL_입고;
--==>>
/*
입고번호	상품코드    	입고일자	    입고수량    	입고단가
3	    H001	        2023-11-06	50	        500
4	    H002        	2023-11-06	30	        400
1	    H001        	2023-11-06	30	        500
2	    H002        	2023-11-06	20	        400
5	    H003        	2023-11-06	35	        400
6	    H004	        2023-11-06	70	        500
7	    C001	    2023-11-06	26	        1400
8	    C001	    2023-11-06	24	        1400
9	    C001	    2023-11-06	20	        1500
10  	C002	        2023-11-06	20	        1000
11	    C003	    2023-11-06	20	        1000
12	    C004	    2023-11-06	20	        1000
*/



SELECT *
FROM TBL_출고;
--==>> 조회 결과 없음





EXEC PRC_출고_INSERT('H001', 10, 600);

SELECT *
FROM TBL_출고;


SELECT *
FROM TBL_상품;


EXEC PRC_출고_INSERT('H001', 80, 600);






--○ 생성한 프로시저가 제대로 작동하는지의 여부 확인
--   현재 상품 테이블의 바밤바 재고 수량은 70개
--   프로시저의 호출 의미는 바밤바 10개 출고

EXEC PRC_출고_INSERT2('H001', 10, 600);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.


SELECT *
FROM TBL_상품;
--==>>
/*
상품코드	상품명	소비자가격	재고수량
H001    	바밤바	600	        60
H002    	죠스바	500	        50
H003	    보석바	500	        35
H004	    누가바	600	        70
H005	    쌍쌍바	700	        0
H006    	수박바	500	        0
H007    	알껌바	500	        0
C001	빵빠레	1600	    70
C002	    월드콘	1500	    20
C003	메타콘	1500	    20
C004	구구콘	1600	    20
C005	슈퍼콘	1700	    0
E001	빵또아	2600        	0
E002    	투게더	2500        	0
E003	팥빙수	2500        	0
E004	셀렉션	2600        	0
E005	설레임	2700	        0
*/


EXEC PRC_출고_INSERT2('C001', 20, 1500);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.


EXEC PRC_출고_INSERT2('C001', 20, 1500);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.

EXEC PRC_출고_INSERT2('C001', 10, 1500);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.


EXEC PRC_출고_INSERT2('C001', 30, 1500);
--==>> 에러 발생
--     (ORA-20002: 재고 부족~!!!)


SELECT *
FROM TBL_상품;
--==>>
/*
H001	    바밤바	600	    60
H002	    죠스바	500	    50
H003	    보석바	500	    35
H004    	누가바	600	    70
H005    	쌍쌍바	700	    0
H006	    수박바	500	    0
H007    	알껌바	500	    0
C001	빵빠레	1600	20
C002    	월드콘	1500	20
C003	메타콘	1500	20
C004	구구콘	1600	20
C005	슈퍼콘	1700	0
E001	빵또아	2600    	0
E002    	투게더	2500    	0
E003	팥빙수	2500	    0
E004	셀렉션	2600    	0
E005	설레임	2700    	0
*/



EXEC PRC_출고_INSERT2('H001', 10, 500);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.

EXEC PRC_출고_INSERT2('H001', 10, 500);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.

EXEC PRC_출고_INSERT2('H001', 10, 500);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.


SELECT *
FROM TBL_상품;


EXEC PRC_출고_INSERT2('H002', 20, 500);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.

EXEC PRC_출고_INSERT2('H003', 15, 500);
--==>> PL/SQL 프로시저가 성공적으로 완료되었습니다.


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

SELECT *
FROM TBL_상품;
--==>>
/*
상품코드	상품명	소비자가격	재고수량
H001	    바밤바	600	        30
H002	    죠스바	500	        30
H003	    보석바	500	        20
H004    	누가바	600	        70
H005    	쌍쌍바	700	        0
H006	    수박바	500	        0
H007	    알껌바	500	        0
C001	빵빠레	1600	    20
C002	    월드콘	1500	    20
C003	메타콘	1500	    20
C004	구구콘	1600	    20
C005	슈퍼콘	1700	    0
E001	빵또아	2600        	0
E002	    투게더	2500        	0
E003	팥빙수	2500	        0
E004	셀렉션	2600	        0
E005	설레임	2700	        0
*/


SELECT *
FROM TBL_출고;
--==>>
/*
출고번호	상품코드	    출고일자	    출고수량    	출고단가
2	    H001        	2023-11-06	10	        600
1	    H001	        2023-11-06	10	        600
3	    C001	    2023-11-06	20	        1500
4	    C001	    2023-11-06	20	        1500
5	    C001	    2023-11-06	10	        1500
6	    H001	        2023-11-06	10	        500
7	    H001        	2023-11-06	10	        500
8	    H001        	2023-11-06	10	        500
9	    H002        	2023-11-06	20	        500
10	    H003        	2023-11-06	15	        500
*/



EXEC PRC_출고_UPDATE(1, 15);
EXEC PRC_출고_UPDATE(1, 43);