일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 직장인일기
- 넷플릭스
- ROWNUM
- Drop
- 책리뷰
- Update
- 홈트
- 빅데이터
- 직장생활
- 30일챌린지
- SQL
- ERD
- INSERT
- where절
- SQLD
- constraint
- 데이터모델링
- 환생
- rename
- 인덱스
- null
- 회사싫어
- 도전
- data
- 회사생활
- 일기
- 테이블삭제
- 전생
- 30일글쓰기
- 보울룸
- Today
- Total
최보름달
[SQL] Procedure, Function, Trigger 본문
Procedure 생성 예제
SCOTT 유저가 소유하고 있는 DEPT 테이블에 새로운 부서를 등록하는 프로시저 만드는 예제
SCOTT 유저가 소유한 DEPT 테이블의 구조는 다음과 같음.
<DEPT 테이블>
컬럼 | 타입 | 길이 | 인덱스 |
DEPTNO | NUMBER | 2 | PK |
DNAME | VARCHAR2 | 14 | |
LOC | VARCHAR2 | 13 |
오라클
CRAETE OR REPLACE procedure p_DEPT_insert ---- (1)
(v_DEPTNO in number,
v_dname in varchar2,
v_loc in varchar2,
v_result out varchar2)
IS
cnt number := 0;
BEGIN ---- (2)
SELECT COUNT(*) INTO CNT
FROM DEPT
WHERE DEPTNO = v_DEPTNO ---- (3)
AND ROWNUM = 1 ;
if cnt > 0 then
v_result := '이미 등록된 부서번호이다';
else
INSERT INTO DEPT (DEPTNO, ENAME, LOC) ---- (4)
VALUES (v_DEPTNO, v_dname, v_loc);
COMMIT ; ---- (5)
v_result := '입력완료!!' ;
end if;
EXCEPTION ---- (6)
WHEN OTHERS THEN
ROLLBACK ;
v_result := 'ERROR 발생';
END ;
/
sql server
CREATE procedure dbo.p_DEPT_insert ---- (1)
@v_DEPTNO int,
@v_dname varchar(30),
@v_loc varchar(30),
@v_result varchar(100) OUTPUT
AS
DELARE @cnt int
BEGIN
SELECT @cnt = COUNT(*) ---- (2)
FROM DEPT
WHERE DEPTNO = @v_DEPTNO
IF @cnt > 0 ---- (3)
BEGIN
SET @v_result = '이미 등록된 부서번호이다'
RETURN
END
ELSE
BEGIN
BEGIN TRAN
INSERT INTO DEPT (DEPTNO, DNAME, LOC) ---- (4)
VALUSE (@v_DEPTNO, @v_dname, @v_loc)
IF @@ERROR <> 0
BEGIN
ROLLBACK ---- (6)
SET @v_result = 'ERROR 발생'
RETURN
END
ELSE
BEGIN
COMMIT ---- (5)
SET @v_result = '입력완료!!'
RETURN
END
END
END
- DEPT 테이블에 들어갈 컬럼 값(부서코드, 부서명, 위치) 을 입력 받는다.
- 입력 받은 부서코드가 존재하는지 확인한다.
- 부서코드가 존재하면 '이미 등록된 부서입니다' 라는 메세지를 출력값에 넣는다.
- 부서코드가 존재하지 않으면 입력받은 필드값으로 새로운 부서 레코드를 입력한다.
- 새로운 부서가 정상적으로 입력됐을 경우에는 COMMIT 명령
- 에러가 발생하면 모든 트랜잭션을 취소하고 'ERROR 발생'을 출력.
프로시저 작성 시 주의할 점
- PL/SQL 및 T-SQL 에는 다양한 변수가 있다. 예제에 나온 cnt 라는 변수를 SCALAR 변수라고 한다. SCALAR 변수는 사용자의 임시 데이터를 하나만 저장할 수 있는 변수이며 거의 모든 형태의 데이터 유형을 지정할 수 있다.
- PL/SQL 에서 사용하는 SQL 구문 중 SELECT 문장은 결과값이 반드시 있어야 하고, 결과값은 하나여야 한다. 조회결과가 없거나 하나가 아니면 에러가 발생한다. (T-SQL은 결과값이 없어도 에러가 발생하지 않음)
- T-SQL 을 비롯한 일반적인 대입 연산자는 '=' 를 사용하지만 PL/SQL 에서는 ':=' 를 사용한다.
- 에러를 처리하는 EXCEPTION 에는 WHEN ~ TEHN 절을 사용하여 에러의 종류별로 적절히 처리한다.
오라클 실행결과
[실행 결과]
Oracle SQL> SELECT * FROM DEPT; -----------------①
DEPTNO DNAME LOC
------- ------- ---------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL> variable rslt varchar2(30); -----------------②
SQL> EXECUTE p_DEPT_insert(10,'dev','seoul',:rslt); -----------------③
PL/SQL 처리가 정상적으로 완료되었다.
SQL> print rslt; -----------------④
RSLT
--------------------------------
이미 등록된 부서번호이다
SQL> EXECUTE p_DEPT_insert(50,'NewDev','seoul',:rslt); ----------------⑤ PL/SQL 처리가 정상적으로 완료되었다.
SQL> print rslt; ----------------⑥
RSLT
-------------------------------- 입력 완료!!
SQL> SELECT * FROM DEPT; ----------------⑦
DEPTNO DNAME LOC
------ -------- ---------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
50 NewDev SEOUL
5개의 행이 선택되었다.
- DEPT 테이블을 조회하면 총 4개 행의 결과가 출력된다.
- procedure 를 실행할 결과값을 받을 변수를 선언한다 (BIND 변수)
- 존재하는 DEPTNO(10)을 가지고 procedure 를 실행한다.
- DEPTNO 가 10 인 부서는 이미 존재하기 때문에 rslt를 출력해보면 '이미 등록된 부서번호이다' 라고 출력된다.
- DEPTNO(50) 을 입력한다.
- rslt 를 출력해보면 '입력완료' 라고 나온다.
- DEPT 테이블을 조회해보면 DEPTNO가 50인 데이터가 저장되었다.
sql server 생략
User-Defined Function 의 생성과 활용
User Defined Function 은 procedure 처럼 절차형 SQL을 로직과 함께 데이터베이스 내에 저장해 놓은 명령문의 집합을 의미한다.
SUM, SUBSTR, NVL등의 함수는 벤더에서 미리 만들어둔 내장 함수이고, 사용자가 별도의 함수를 만들 수도 있다.
Function 이 procedure 와 다른 점은 RETURN 을 사용해서 하나의 값을 반드시 되돌려 줘야 한다는 것이다.
즉, Function 은 특정 작업을 수앻아고 반드시 수행 결과 값을 리턴한다.
8월 경기결과와 두 팀간의 점수차를 ABS 함수를 이용해서 절대값으로 출력한다.
오라클
SELECT SCHE_DATE 경기일자,
HOMETEAM_ID || '-' || AWAYTEAM_ID 팀들,
HOME_SCORE || '-' || AWAY_SCORE,
ABS(HOME_SCORE - AWAY_SCORE) 점수차
FROM SCHEDULE
WHERE GUBUN = 'Y'
AND SCHE_DATE BETWEEN '20120801' AND '20120831'
ORDER BY SCHE_DATE ;
위에서 사용한 ABS 함수를 만드는데, INPUT 값으로 숫자만 들어온다고 가정한다.
CERATE OR REPLACE function UTIL_ABS
(v_input in number) ---- (1)
return NUMBER
IS
v_return number := 0 ; ---- (2)
BEGIN
if v_input < 0 then ---- (3)
v_return := v_input * 1;
else
v_return := v_input ;
end if ; ---- (4)
RETURN v_return ;
END ;
/
UTIL_ABS function 의 처리과정
- 숫자 값을 입력 받는다. 예제에서는 숫자 값만 입력된다고 가정한다.
- 리턴 값을 받아 줄 변수인 v_return 을 선언한다.
- 입력값이 음수이면 -1 을 곱하여 v_return 변수에 대입한다.
- v_return 변수를 리턴한다.
Trigger 생성과 활용
Trigger란 특정한 테이블에 INSERT, UPDATE, DELETE 와 같은 DML 문이 수행되었을 때, 데이터베이스에서 자동으로 동작하도록 작성된 프로그램이다. 사용자가 직접 호출하여 사용하는 것이 아니고, 데이터베이스 내에서 자동으로 수행하게 된다.
트리거는 테이블과 뷰, 데이터베이스 작업을 대상으로 정의할 수 있고, 전체 트랜잭션 작업에 대해 발생되는 트리거와 각 행에 대해서 발생되는 트리거가 있다.
ORDER_LIST에 주문 정보가 입력되면
주문 정보의 주문 일자(ORDER_LIST.ORDER_DATE) 와
주문 상품(ORDER_LIST.PRODUCT) 을 기준으로
판매 집계 테이블(SALES_PER_DATE)에 해당 주문 일자의 주문 상품 레코드가 존재하면 판매수량과 판매 금액을 더하고,
존재하지 않으면 새로운 레코드를 입력한다 <- 는 트리거를 만들어보자.
오라클
CREATE OR REPLACE trigger SUMMARY_SALES ---- (1)
AFTER INSERT
ON ORDER_LIST
FOR EACH ROW
DECLARE ---- (2)
o_date ORDER_LIST.order_date%TYPE;
o_prod ORDER_LIST.product%TYPE;
BEGIN
o_date := NEW.order_date ;
o_prod := NEW.product ;
UPDATE SALES_PER_DATE ---- (3)
SET qty = qty + : NEW.qty,
amount = amount + NEW.amount
WHERE sale_date = o_date
AND product = o+prod;
if SQL%NOTFOUND then ---- (4)
INSERT INTO SALES_PER_DATE
VALUES(o_date, o_prod, : NEW.qty, :NEW.amount);
end if;
END ;
/
(1) 트리거를 선언한다.
CREATE OR REPLACE trigger SUMMARY_SALES : 트리거 선언문
AFTER INSERT : 레코드가 입력된 후 트리거 발생
ON ORDER_LIST : 오더 리스트 테이블에 트리거 설정
FOR EACH ROW : 각 로우마다 트리거 적용
(2) o_date(주문일자), o_prod(주문상품) 값을 저장할 수 있는 변수를 선언하고, 신규로 입력된 데이터를 저장한다.
: NEW 는 신규로 입력된 레코드를 가지고 있는 구조체
: OLD 는 수정, 삭데되기 전의 레코드를 가지고 있는 구조체
(3) 먼저 입력된 주문 내역의 주문 일자와 주문 상품을 기준으로 SALES_PER_DATE 테이블에 업데이트 한다.
(4) 처리 결과가 SQL%NOTFOUND 면 해당 주문 일자의 주문 상품 실적이 존재하지 않으며, SALES_PER_DATE 테이블에 새로운 집계 데이터를 입력한다.
프로시저와 트리거의 차이점
프로시저는 BEGIN ~ END 절 내에 COMMIT, ROLLBACK 같은 트랜잭션 종료 명령어를 사용할 수 있지만,
트리거는 BEGIN ~ END 절 내에 사용할 수 없다.
프로시저 | 트리거 |
CREATE procedure 문법 사용 | CREATE Trigger 문법 사용 |
EXCUTE 명령어로 실행 | 생성 후 자동으로 실행 |
COMMIT, ROLLBACK 실행 가능 | COMMIT, ROLLBACK 사용안됨 |
kdata 한국데이터진흥원에서 출간한 SQL 전문가 가이드 2013 Edition을 요약했습니다.
'문송한 회사생활 > SQL 공부' 카테고리의 다른 글
[SQL] 옵티마이저 실행계획 (0) | 2020.08.21 |
---|---|
[SQL] 옵티마이저(optimizer), 규칙기반/ 비용기반 옵티마이저 (0) | 2020.08.20 |
[SQL] 절차형 SQL (0) | 2020.08.18 |
[SQL] DCL (DATE CONTROL LANGUAGE) (0) | 2020.08.17 |
[SQL] 윈도우 함수 (WINDOW FUNCTION) (1) | 2020.08.17 |