- PL/SQL :
- 일반 프로그래밍 언어 요소를 다 갖고 있으며, 데이터베이스 업무를 처리하기 위한 최적화된 언어
- BLOCK 구조로 다수의 SQL 문을 한번에 처리하므로 수행 속도가 빠름
SET SERVEROUTPUT ON;
console.log()
, System.out.println()
과 같은 역할BEGIN
-- console.log(), System.out.println() 과 같은 역할
DBMS_OUTPUT.PUT_LINE('HELLO WORLD!');
END;
/ -- PL/SQL 끝
DECLARE
-- 외부에서 데이터가 들어옴
-- 변수 변경부분
-- int V_NUM = 1234;
V_NUM NUMBER(4) := 1234;
-- String V_STR = "";
V_STR VARCHAR2(10);
BEGIN
-- 여기부터 만들어 놓은 테이블을 이용해서 INSERT, UPDATE등 명령을 내림
V_STR := 'HELLO!';
-- '+' 를 쓰지않고 || 표시로 합친다.
DBMS_OUTPUT.PUT_LINE('V_NUM 값은 : ' || v_NUM);
DBMS_OUTPUT.PUT_LINE('V_STR 값은 : ' || v_STR);
END;
/
DECLARE
-- 변수
V_SCORE NUMBER := 95;
V_GRADE VARCHAR2(2) := '';
BEGIN
-- 실행부분
IF(V_SCORE >=90)
THEN V_GRADE := 'A';
ELSIF (V_SCORE >= 80)
THEN V_GRADE := 'B';
ELSIF (V_SCORE >= 70)
THEN V_GRADE := 'C';
ELSE
V_GRADE := 'F';
END IF;
-- 출력
DBMS_OUTPUT.PUT_LINE('점수 : ' || v_SCORE || ', 등급 : ' || v_GRADE);
END;
/
for(int I=0; I<=9; I++)
와 같음DECLARE
-- 변수설정
V_NUM NUMBER := 13;
BEGIN
-- 실행
-- for(int I=0; I<=9; I++)
FOR I IN 1..9 LOOP
-- 출력
DBMS_OUTPUT.PUT_LINE(V_NUM || '*' || I || '=' || V_NUM*I);
-- 여기에 INSERT INTO 또는 다른 쿼리문을 쓰면 반복 수행한다.
END LOOP;
END;
/
MOD(숫자, 나눌숫자)
나머지 구하기IF MOD(I, 2) = 0
=> I를 2로 나눠서 나머지가 0 = 짝수DECLARE
-- 변수
-- 외부에서 들어오는 부분
V_NUM NUMBER(3) := 10;
BEGIN
FOR I IN 1..V_NUM LOOP
-- MOD : 나머지 구하는것 => 2로 나누어서 나머지가 0일때
IF MOD(I, 2) = 0
THEN DBMS_OUTPUT.PUT_LINE( I || '는 짝수' );
ELSE
DBMS_OUTPUT.PUT_LINE( I || '는 홀수' );
END IF;
END LOOP;
END;
/
INSERT INTO 테이블명(컬럼명) VALUES(추가할값);
DECLARE
-- 변수정의
-- 정의할 변수 없음 생략
BEGIN
-- 수행
-- INSERT INTO 테이블명(컬럼명) VALUES(추가할값);
INSERT INTO MEMBER2(USERID, USERPW, USERNAME, USERAGE, USERDATE)
VALUES('B', 'B', '임보람', 36, CURRENT_DATE);
-- 성공하면 COMMIT;
COMMIT;
EXCEPTION
-- 오류처리
WHEN OTHERS THEN --모든 예외의 경우
ROLLBACK; -- ROLLBACK;
END;
/
-- 조회
SELECT * FROM MEMBER2;
DECLARE
-- 변수정의
-- 정의할 변수 없음 생략
BEGIN
-- 수행
-- INSERT INTO 테이블명(컬럼명) VALUES(추가할값);
FOR I IN 1..10 LOOP
INSERT INTO MEMBER2(USERID, USERPW, USERNAME, USERAGE, USERDATE)
VALUES('A'||I, 'A', '반복맨'||I, 20+I, CURRENT_DATE);
END LOOP;
-- 성공하면 COMMIT;
COMMIT;
EXCEPTION
-- 오류처리
WHEN OTHERS THEN --모든 예외의 경우
ROLLBACK; -- ROLLBACK;
END;
/
-- 조회
SELECT * FROM MEMBER2;
DECLARE
V_MEM2 MEMBER2%ROWTYPE;
-- 타입 일치시켜야함
-- V_USERID VARCHAR2(30);
-- BUT, 이건 타입 바로 가지고 옴
V_USERID MEMBER2.USERID%TYPE; -- VARCHAR2(30)
BEGIN
-- SELECT * FROM 테이블명 WHERE 조건;
SELECT * INTO V_MEM2 FROM MEMBER2 WHERE USERID='A';
DBMS_OUTPUT.PUT_LINE( V_MEM2.USERID );
DBMS_OUTPUT.PUT_LINE( V_MEM2.USERNAME );
END;
/
DECLARE
-- CURSOR CUR IS (조회하고자하는 SQL);
CURSOR CUR IS (SELECT * FROM MEMBER2);
BEGIN
-- CUR 만큼 반복
FOR TMP IN CUR() LOOP
DBMS_OUTPUT.PUT_LINE( 'USERID : '|| TMP.USERID );
END LOOP;
END;
/
CREATE OR REPLACE PROCEDURE "프로시저명"(
"파라미터명" IN "타입"
)
IS
"변수명" "변수타입"
BEGIN
"프로시저 내용"
END;
/
CREATE OR REPLACE PROCEDURE PROC_IF_EXAM(
-- "파라미터명" IN "타입"
V_SCORE IN NUMBER -- 외부에서 숫자 하나가 전달되어야 함. 의무, 안받을꺼면 변수정의 필요없음
)
IS
-- "변수명" "변수타입"
V_GRADE VARCHAR2(2);
BEGIN
-- "프로시저 내용"
IF(V_SCORE >=90)
THEN V_GRADE := 'A';
ELSIF (V_SCORE >= 80)
THEN V_GRADE := 'B';
ELSIF (V_SCORE >= 70)
THEN V_GRADE := 'C';
ELSE
V_GRADE := 'F';
END IF;
DBMS_OUTPUT.PUT_LINE(V_GRADE);
END;
/
-- 실행하면 'Procedure PROC_IF_EXAM이(가) 컴파일되었습니다.'
-- 외부에서 사용
EXEC PROC_IF_EXAM(88);
CREATE OR REPLACE PROCEDURE PROC_CAL(
-- "파라미터명" IN "타입"
V_NUM IN NUMBER
)
IS
-- "변수명" "변수타입"
-- V_ASW NUMBER;
BEGIN
-- "프로시저 내용"
FOR I IN 1..9 LOOP
DBMS_OUTPUT.PUT_LINE(V_NUM||'*'||I||'='||V_NUM*I);
END LOOP;
END;
/
--외부에서 사용
EXEC PROC_CAL(3);
MEMBER2.USERID%TYPE
를 쓰면 타입을 자동으로 불러온다.%TYPE
CREATE OR REPLACE PROCEDURE PROC_INSERT_EXAM(
-- "파라미터명" IN "타입"
V_ID IN MEMBER2.USERID%TYPE,
V_PW IN MEMBER2.USERPW%TYPE,
V_NA IN MEMBER2.USERNAME%TYPE,
V_AG IN MEMBER2.USERAGE%TYPE
)
IS
-- 임시변수 필요없어서 생략
-- "변수명" "변수타입"
BEGIN
-- 수행
-- "프로시저 내용"
INSERT INTO MEMBER2(USERID, USERPW, USERNAME, USERAGE, USERDATE)
VALUES(V_ID, V_PW, V_NA, V_AG, CURRENT_DATE);
COMMIT;
DBMS_OUTPUT.PUT_LINE('INSERT 성공');
EXCEPTION
-- 오류처리
WHEN OTHERS THEN --모든 예외의 경우
ROLLBACK; -- ROLLBACK;
DBMS_OUTPUT.PUT_LINE('INSERT 실패');
END;
/
-- 프로시저 실행
EXEC PROC_INSERT_EXAM('C','C','별이',7);
-- 조회
SELECT * FROM MEMBER2;
V_CHK
는 임시변수, 0은 존재하지않는다, 1은 존재한다.SELECT COUNT(*) INTO V_CHK FROM MEMBER2 WHERE USERID = V_ID;
USERID = V_ID
를 조회해서 같은 아이디의 개수를 구하고(COUNT(*)
) 그 개수를 V_CHK에 담는다(INTO V_CHK
)CREATE OR REPLACE PROCEDURE PROC_UPSERT_EXAM(
-- "파라미터명" IN "타입"
V_ID IN MEMBER2.USERID%TYPE,
V_PW IN MEMBER2.USERPW%TYPE,
V_NA IN MEMBER2.USERNAME%TYPE,
V_AG IN MEMBER2.USERAGE%TYPE
)
IS
-- "변수명" "변수타입"
-- 존재하는지 하지않는지 보관하는 변수 (0, 1)
V_CHK NUMBER(2) := 0;
BEGIN
-- 수행
-- "프로시저 내용"
-- V_ID와 일치하는 아이디 개수를 구함
-- 'INTO 변수명' 하면 내용이 변수에 담김
SELECT COUNT(*) INTO V_CHK FROM MEMBER2 WHERE USERID = V_ID;
IF (V_CHK <= 0) THEN
INSERT INTO MEMBER2(USERID, USERPW, USERNAME, USERAGE, USERDATE)
VALUES(V_ID, V_PW, V_NA, V_AG, CURRENT_DATE);
DBMS_OUTPUT.PUT_LINE('INSERT 성공');
ELSE
UPDATE MEMBER2 SET USERPW = V_PW, USERNAME = V_NA, USERAGE = V_AG
WHERE USERID = V_ID;
DBMS_OUTPUT.PUT_LINE('UPDATE 성공');
END IF;
COMMIT;
EXCEPTION
-- 오류처리
WHEN OTHERS THEN --모든 예외의 경우
ROLLBACK; -- ROLLBACK;
DBMS_OUTPUT.PUT_LINE('UPSERT 실패');
END;
/
-- 프로시저 실행
EXEC PROC_UPSERT_EXAM('W','W','별이',5);
-- 조회
SELECT * FROM MEMBER2;
EXEC
를 못쓴다.OUT
으로 정했기때문에 반환값을 받을 수 있는 형태로 실행해야한다.DECLARE
에서 변수 설정, BEGIN
에서 실행 후 결과 출력CREATE OR REPLACE PROCEDURE PROC_DELETE_EXAM(
-- "파라미터명" IN "타입"
V_ID IN MEMBER2.USERID%TYPE,
V_CHK OUT NUMBER
)
IS
-- "변수명" "변수타입"
BEGIN
-- DELETE FROM 테이블명 WHERE 조건;
DELETE FROM MEMBER2 WHERE USERID = V_ID;
COMMIT;
V_CHK := 1;
EXCEPTION
-- 오류처리
WHEN OTHERS THEN --모든 예외의 경우
ROLLBACK; -- ROLLBACK;
V_CHK := 0;
END;
/
-- 프로시저 실행 테스트
DECLARE
T_ID MEMBER2.USERID%TYPE := 'A5';
T_CHK NUMBER := 0;
BEGIN
PROC_DELETE_EXAM(T_ID, T_CHK);
DBMS_OUTPUT.PUT_LINE('결과출력 : '||T_CHK);
END;
/
-- EXEC PROC_DELETE_EXAM('A1'); -- 이거 아님
-- 조회
SELECT * FROM MEMBER2;
- BOARD3 테이블
- 값을 전달했을때 추가되는 PROC_BRD_INSERT(0,1)
- 글번호가 없으면 추가, 있으면 조회수를 1증가 PROC_BRD_UPSERT (0,1)
- 작성자가 일치하는 항목을 삭제하는 PROC_BRD_DELETE (0,1)
- 조건에 해당하는 항목의 개수를 반환하는 PROC_BRD_SELECT (N개)
CREATE OR REPLACE PROCEDURE PROC_BRD_INSERT (
-- "파라미터명" IN "타입"
-- IN_NO IN BOARD3.NO%TYPE,
IN_TITLE IN BOARD3.TITLE%TYPE,
IN_CONTENT IN BOARD3.CONTENT%TYPE,
IN_WRITER IN BOARD3.WRITER%TYPE,
-- IN_HIT IN BOARD3.HIT%TYPE,
OUT_CHK OUT NUMBER
)
IS
-- "변수명" "변수타입"
BEGIN
INSERT INTO BOARD3(NO, TITLE, CONTENT, WRITER, HIT, REGDATE)
VALUES(SEQ_BOARD3_NO.NEXTVAL, IN_TITLE, IN_CONTENT, IN_WRITER, 1, CURRENT_DATE);
COMMIT;
OUT_CHK := 1;
EXCEPTION
-- 오류처리
WHEN OTHERS THEN --모든 예외의 경우
ROLLBACK; -- ROLLBACK;
OUT_CHK := 0;
END;
/
-- 프로시저 테스트
DECLARE
T_TITLE BOARD3.TITLE%TYPE := 'AA';
T_CONTENT BOARD3.CONTENT%TYPE := 'AA';
T_WRITER BOARD3.WRITER%TYPE := 'AR';
-- T_HIT BOARD3.HIT%TYPE := 1;
T_CHK NUMBER := 0;
BEGIN
PROC_BRD_INSERT(T_TITLE, T_CONTENT, T_WRITER, T_CHK);
DBMS_OUTPUT.put_line('결과 : ' || T_CHK);
END;
/
SELECT * FROM BOARD3;
SELECT * FROM MEMBER3;
CREATE OR REPLACE PROCEDURE PROC_BRD_UPSERT(
-- "파라미터명" IN "타입"
IN_NO IN BOARD3.NO%TYPE,
IN_TITLE IN BOARD3.TITLE%TYPE,
IN_CONTENT IN BOARD3.CONTENT%TYPE,
IN_WRITER IN BOARD3.WRITER%TYPE,
OUT_CHK OUT NUMBER
)
IS
-- "변수명" "변수타입"
V_CHK NUMBER := 0;
BEGIN
-- "프로시저 내용"
SELECT COUNT(*) INTO V_CHK FROM BOARD3 WHERE NO = IN_NO;
IF (V_CHK <= 0) THEN
INSERT INTO BOARD3(NO, TITLE, CONTENT, WRITER, HIT, REGDATE)
VALUES(SEQ_BOARD3_NO.NEXTVAL, IN_TITLE, IN_CONTENT, IN_WRITER, 1, CURRENT_DATE);
COMMIT;
OUT_CHK := 0;
ELSE
UPDATE BOARD3 SET HIT = HIT+1 WHERE NO = IN_NO;
COMMIT;
OUT_CHK := 1;
END IF;
EXCEPTION
-- 오류처리
WHEN OTHERS THEN --모든 예외의 경우
ROLLBACK; -- ROLLBACK;
OUT_CHK := -1;
END;
/
-- 프로시저 테스트
DECLARE
T_NO BOARD3.NO%TYPE := 55;
T_TITLE BOARD3.TITLE%TYPE := 'BB';
T_CONTENT BOARD3.CONTENT%TYPE := 'BB';
T_WRITER BOARD3.WRITER%TYPE := 'B';
T_CHK NUMBER := 0;
BEGIN
PROC_BRD_UPSERT(T_NO, T_TITLE, T_CONTENT, T_WRITER, T_CHK);
DBMS_OUTPUT.put_line('결과 : ' || T_CHK);
END;
/
SELECT * FROM BOARD3;
SELECT * FROM MEMBER3;
CREATE OR REPLACE PROCEDURE PROC_BRD_DELETE(
-- "파라미터명" IN "타입"
IN_WRITER IN BOARD3.WRITER%TYPE,
OUT_CHK OUT NUMBER
)
IS
-- "변수명" "변수타입"
BEGIN
-- "프로시저 내용"
DELETE FROM BOARD3 WHERE WRITER = IN_WRITER;
COMMIT;
OUT_CHK := 1;
EXCEPTION
-- 오류처리
WHEN OTHERS THEN --모든 예외의 경우
ROLLBACK; -- ROLLBACK;
OUT_CHK := 0;
END;
/
-- 프로시저 테스트
DECLARE
T_WRITER BOARD3.WRITER%TYPE := 'A';
T_CHK NUMBER := 0;
BEGIN
PROC_BRD_DELETE(T_WRITER, T_CHK);
DBMS_OUTPUT.put_line('결과 : ' || T_CHK);
END;
/
SELECT * FROM BOARD3;
SELECT * FROM MEMBER3;
CREATE OR REPLACE PROCEDURE PROC_BRD_SELECT(
-- "파라미터명" IN "타입"
IN_HIT IN BOARD3.HIT%TYPE,
OUT_CHK OUT NUMBER
)
IS
-- "변수명" "변수타입"
BEGIN
-- "프로시저 내용"
SELECT COUNT(*) INTO OUT_CHK FROM BOARD3 WHERE HIT > IN_HIT;
EXCEPTION
-- 오류처리
WHEN OTHERS THEN --모든 예외의 경우
ROLLBACK; -- ROLLBACK;
OUT_CHK := -1;
END;
/
-- 프로시저 테스트
DECLARE
T_HIT BOARD3.HIT%TYPE := 10;
T_CHK NUMBER := 0;
BEGIN
PROC_BRD_SELECT(T_HIT, T_CHK);
DBMS_OUTPUT.put_line('결과 : ' || T_CHK);
DBMS_OUTPUT.put_line('조회수 10이상 게시물 수 : ' || T_CHK);
END;
/
SELECT * FROM BOARD3;
SELECT * FROM MEMBER3;