250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 낙관적락
- 힙
- execute
- 지연로딩
- 즉시로딩
- 유니크제약조건
- 데코레이터
- 다대다
- SQL프로그래밍
- 스프링 폼
- 동적sql
- exclusive lock
- 비관적락
- PS
- 연관관계
- eager
- 일대다
- dfs
- 다대일
- shared lock
- querydsl
- CHECK OPTION
- 이진탐색
- 스토어드 프로시저
- FetchType
- JPQL
- 백트래킹
- 연결리스트
- BOJ
- fetch
Archives
- Today
- Total
흰 스타렉스에서 내가 내리지
SQL 프로그래밍 - 스토어드 프로시저, IF, CASE, WHILE, 동적 SQL 본문
728x90
# 스토어드 프로시저
DELIMITER $$
CREATE PROCEDURE myProcedure()
BEGIN
<SQL 문 ~~>
END $$
DELIMITER ;
CALL myProcedure();
- 세미콜론 (;) 으로는 SQL 의 끝인지, 스토어드 프로시저의 끝인지 구별할 수 없어서 $$ 를 사용한다.
* 스토어드 프로시저 매개변수
# 1. IN
- 프로시저에 값을 전달한다.
DELIMITER $$
CREATE PROCEDURE myProc(IN name VARCHAR(255))
BEGIN
SELECT * FROM Member m
WHERE m.name = name;
END $$
DELIMITER ;
--
CALL myProc('홍길동');
# 2. OUT
- 프로시저의 값을 반환한다.
- 초기값은 프로시저 내에서 NULL 이며, 프로시저가 반환될 때 새로운 값이 호출자에게 리턴된다.
DELIMITER $$
CREATE PROCEDURE myProc(IN name VARCHAR(255), OUT total INT)
BEGIN
SELECT count(m)
INTO total
FROM Member m
WHERE m.name = name;
END $$
DELIMITER ;
--
CALL myProc('홍길동', @total);
SELECT @total; -- @total 값 호출
# 3. INOUT
- 호출자에 의해 하나의 변수가 초기화되고 프로시저에 의해 수정된다. IN + OUT
- 프로시저가 리턴할 때 프로시저가 변경한 사항은 호출자에게 리턴된다.
DELIMITER $$
CREATE PROCEDURE add_counter (INOUT count INT(4), IN x INT(4))
BEGIN
SET count = count + x;
END $$
DELIMITER ;
--
SET @counter = 10;
CALL add_counter (@counter, 1); -- SELECT @counter = 11
CALL add_counter (@counter, 2); -- SELECT @counter = 13
CALL add_counter (@counter, 5); -- SELECT @counter = 18
# IF 문
IF <조건식> THEN
SQL문장들
END IF;
- SQL 문장들이 한 문장이라면 그 문장만 써도 되지만, 두 문장 이상이 처리되어야 할 때는 BEGIN ~ END 로 묶어줘야 한다.
* 활용 예제
DROP PROCEDURE IF EXISTS myProc;
DELIMITER $$
CREATE PROCEDURE myProc()
BEGIN
DECLARE debutDate DATE; -- 1
DECLARE curDate DATE;
DECLARE days INT;
SELECT debut_date INTO debutDate -- 2
FROM member
WHERE mem_id = 'APN';
SET curDATE = CURRENT_DATE(); -- 3
SET days = DATEDIFF(curDATE, debutDate); -- 4
IF (days/365) >= 5 THEN -- 5
SELECT CONCAT('데뷔', days, '일');
ELSE
SELECT CONCAT('데뷔', days, '일');
END IF;
END $$
DELIMITER ;
CALL myProc();
- 1. 변수를 3개 준비했다.
- 2. INTO 변수가 붙었다. 이럴 경우 결과를 변수에 저장한다.
- 3. CURRENT_DATE() 함수로 현재 날짜를 curDate 에 저장한다.
- 4. DATEDIFF() 함수로 날짜 차이를 days 에 저장한다.
- 5. IF ~ ELSE ~ END IF
# CASE 문
* 형식
CASE
WHEN 조건1 THEN
SQL 문
WHEN 조건2 THEN
SQL 문
ELSE
SQL 문
END CASE;
* 예제
SELECT M.mem_id, M.mem_name, SUM(price*amount) "총구매액",
CASE
WHEN (SUM(price*amount) >= 1500) THEN '최우수고객'
WHEN (SUM(price*amount) >= 1000) THEN '우수고객'
WHEN (SUM(price*amount) >= 1) THEN '일반고객'
ELSE '유령고객'
END "회원등급"
FROM buy B
RIGHT OUTER JOIN Member M
ON B.mem_id = M.mem_id
GROUP BY M.mem_id
ORDER BY SUM(price*amount) DESC;
# WHILE 문
* 형식
WHILE <조건식> DO
SQL 문장
END WHILE;
* 예제 - 1에서 100까지 값을 모두 더하기
DROP PROCEDURE IF EXISTS whileProc;
DELIMITER $$
CREATE PROCEDURE whileProc()
BEGIN
DECLARE i INT; -- 1에서 100까지 증가할 변수
DECLARE hap INT; -- 더한 값을 누적할 변수
SET i = 1;
SET hap = 0;
WHILE (i <= 100) DO
SET hap = hap + i;
SET i = i + 1;
END WHILE;
SELECT '합 --> ', hap;
END $$
DELIMITER ;
CALL whileProc();
* WHILE 문의 응용
- 1에서 100까지 합계에서 4의 배수를 제외시켜보자. 그리고 숫자를 더하는 중간에 합계가 1,000이 넘으면 더하는 것을 그만두자.
- 이럴 떄는 ITERATE 와 LEAVE 문을 사용한다.
- ITERATE [레이블] : 지정한 레이블로 가서 계속 진행한다. (CONTINUE)
- LEAVE [레이블] : 지정한 레이블을 빠져나가낟. 즉, WHILE 문이 종료된다. (BREAK)
DROP PROCEDURE IF EXISTS whileProc2;
DELIMITER $$
CREATE PROCEDURE whileProc2()
BEGIN
DECLARE i INT;
DECLARE hap INT;
SET i = 1;
SET hap = 0;
myWhile:
WHILE (i <= 100) DO
IF (i%4 = 0) THEN
SET i = i + 1;
ITERATE myWhile; -- 지정한 label 문으로 가서 계속 진행
END IF;
SET hap = hap + i;
IF (hap > 1000) THEN
LEAVE myWhile; -- 지정한 label 문을 떠남. 즉 While 종료
END IF;
SET i = i + 1;
END WHILE;
SELECT '1부터 100까지의 합 (4의 배수 제외), 1000 넘으면 종료 --> ', hap;
END $$
DELIMITER ;
CALL whileProc2();
# PREPARE 와 EXECUTE
- PREPARE 는 SQL 문을 실행하지는 않고 미리 준비만 해놓고, EXECUTE 는 준비한 SQL 을 실행합니다.
- 그리고 실행 후에는 DEALLOCATE PREPARE 로 문장을 해제해주는 것이 바람직하다.
PREPARE myQuery FROM 'SELECT * FROM member WHERE mem_id = "BLK"';
EXECUTE myQuery;
DEALLOCATE PREPARE myQuery;
- 이렇게 미리 SQL을 준비한 후에 나중에 실행하는 것을 동적 SQL 이라고 한다.
* 동적 SQL 의 활용
- PREPARE 문에서는 ? 로 향후에 입력될 값을 비워 놓고, EXECUTE 에서 USING 으로 ? 에 값을 전달할 수 있다.
- 다음 예제는 실무에서 종종 사용된다.
- 보안이 중요한 출입문에서는 출입한 내역을 테이블에 기록해 놓는다.
- 이때 출입증을 태그하는 순간의 날짜와 시간이 INSERT 문으로 만들어져서 입력되도록 한다.
DROP TABLE IF EXISTS gate_table;
CREATE TABLE gate_table (id INT AUTO_INCREMENT PRIMARY KEY, entry_time DATETIME);
SET @curDate = CURRENT_TIMESTAMP(); -- 현재 날짜와 시간
PREPARE myQuery FROM 'INSERT INTO gate_table VALUES(NULL, ?)';
EXECUTE myQuery USING @curDate;
DEALLOCATE PREPARE myQuery;
SELECT * FROM gate_table;
- 결국 이 SQL 을 실행한 시점의 날짜와 시간이 입력된다.
'SQL' 카테고리의 다른 글
[SQL] 기본값 정의 (0) | 2024.04.15 |
---|---|
[SQL] 체크 제약 조건 (0) | 2024.04.15 |
내부 조인과 외부 조인 (0) | 2024.04.10 |
[SQL] 데이터 형 변환 - 명시적인 변환 (0) | 2024.04.10 |
SQL 에서의 변수 사용, 그리고 PREPARE 와 EXECUTE 절 (0) | 2024.04.10 |