Mysql&DBeaver

DBeaver)procedure, function 안에서 쓸 수 있는 IF

연습노트 2024. 9. 8. 19:06

뭘 하든 경우에 따라 다른 코드를 실행하고 싶은 경우가 많습니다. 

그럴 때 IF / THEN / ELSE 문법을 사용합시다.

 

 

 

 

조건에 따라 다른 SQL 문장을 실행하고 싶다

 

예를 들어봅시다. 

card테이블의 '사용금액' 컬럼 총 합계를 구하는데

총 합계가 500만원이 넘지 않으면 SELECT '분발하세요'

총 합계가 500만원이 넘으면 SELECT '잘했어요'

를 실행하고 싶으면 어떻게 코드를 짜죠?

 

예전에 배운 IF() 또는 CASE 써도 가능하겠지만

그 문법들은 "이 경우엔 A, 저 경우엔 B를 그 자리에 남겨주세요" 이렇게

경우에 따라 문자나 숫자자료를 1개 남겨주는 문법일 뿐이라

조건에 따라 SELECT같은 쿼리문은 남기지 못합니다.  

 

 

 

 

 

조건에 따라 다른 코드를 실행하고 싶으면 IF THEN ELSE

 

이런 경우에는 A코드, 저런 경우에는 B코드를 실행하고 싶으면

IF 조건문이라는 문법을 사용합시다. 

다른 DBMS는 BEGIN/END라고 대충 적으면 그 안에서 IF 문법을 사용할 수 있는 경우가 있는데 

MySQL은 procedure 아니면 function 안에서만 IF를 사용가능합니다. 

 

 

 

IF 조건식1 THEN 
  조건식1이 참이면 실행할 쿼리문;
ELSEIF 조건식2 THEN 
  조건식2가 참이면 실행할 쿼리문;
ELSE 
  그게 아니면 실행할 쿼리문;
END IF;

이런 식으로 사용하는 문법입니다.

- THEN 다음엔 아무거나 넣어도 됩니다. 보통 SQL 쿼리문이 들어갑니다. 

- ELSEIF 부분은 조건식이 여러개 필요없으면 생략해도 됩니다. 

- 조건식이 여러개 맞을 경우 맞은 것들 중 맨 위의 1개만 실행됩니다. CASE문 이랑 동작방식이 유사함 

- 세미콜론 까먹으면 망합니다 

 

 

 

IF 1 > 0 THEN 
  SELECT '맞음';
ELSE 
  SELECT '틀림';
END IF;

예를 들어 위 코드는 뭐가 실행될까요?

뭐게요

 

 

IF 2 = 1 THEN 
  SELECT '첫째가 맞음';
ELSEIF 1 = 1 THEN
  SELECT '둘째가 맞음';
ELSE 
  SELECT '틀림';
END IF;

위 코드는 뭐가 실행될까요?

뭐게요

님이 상상하는 그게 맞습니다. 

확인하려면 직접 procedure 안에서 실행해보십시오. 

[collapse]

 

 

 

 

 

 

그래서 아까로 돌아가서 

card테이블의 '사용금액' 컬럼 총 합계를 구하는데

총 합계가 500만원이 넘지 않으면 SELECT '분발하세요'

총 합계가 500만원이 넘으면 SELECT '잘했어요' 를 실행하고 싶으면 어떻게 코드를 짜야합니까?

빨리 procedure 하나 직접 만들어서 실행해봅시다. 

 

 

해보고 눌러봅시다

 

DROP PROCEDURE IF EXISTS mart.total_sum;

DELIMITER $$
CREATE PROCEDURE mart.total_sum()
BEGIN

  IF (SELECT SUM(사용금액) FROM mart.card) > 5000000 THEN
    SELECT '잘했어요';
  ELSE 
    SELECT '못했어요';
  END IF;

END
$$ 
DELIMITER ;

CALL mart.chk(); 

 

실은 간단히 IF() 또는 CASE 써도 구현가능합니다. 

하지만 조건에 따라 실행시킬 SQL 문법이 길고 복잡하면 오늘 배운 IF 문법 쓰는게 낫습니다. 

 

 

[collapse]

 

 

 

 

 

조건에 따라서 다른 결과를 뱉는 함수만들기 

 

함수() 실행시 파라미터로 나이를 입력했을 때 20살 미만이면 '구매불가' 라는 문자를 뱉고

20살 이상이면 '구매가능' 을 뱉는 함수()를 만들고 싶습니다.

그니까 함수(30); 실행하면 '구매가능'이 그 자리에 남아야한다는 소리입니다. 

 

어떻게 만들죠? 

일단 3분드릴테니 숫자 하나를 입력할 수 있는 함수부터 하나 만들어오십시오. 

 

 

 

DROP FUNCTION IF EXISTS mart.age_check;
DELIMITER $$

CREATE FUNCTION mart.age_check(구멍 INT)
RETURNS INT
DETERMINISTIC
BEGIN 

    RETURN ??;

END $$
DELIMITER ;

SELECT mart.age_check(20);  

이번에도 mart라는 데이터베이스에 하나 만들어봤습니다.

근데 안에 어떻게 코드를 작성하면 될까요?

"구멍자리에 들어온게 20미만이면 RETURN '구매금지', 그게 아니면 RETURN '구매가능' 을 뱉으셈"

이걸 그대로 코드로 옮기면 기능완성아니겠습니까

 

방법은 알려드렸으니 직접 만들어보십시오

 

 

 

DROP FUNCTION IF EXISTS mart.age_check;
DELIMITER $$

CREATE FUNCTION mart.age_check(구멍 INT)
RETURNS VARCHAR(100)
DETERMINISTIC
BEGIN 

    IF 구멍 < 20 THEN  
      RETURN '출입금지';
    ELSE  
      RETURN '출입가능';
    END IF; 
END $$
DELIMITER ;

SELECT mart.age_check(21);  

방법은 여러가지겠지만 저는 이렇게 만들어봤습니다. 

그래서 21살을 넣어서 테스트해보니 결과가 잘 출력되는군요 

 

 

 

[collapse]

 

 

 

 

 

 

오늘의 숙제 : 

 

Q1. 월을 파라미터로 입력하면 '해당 월이 며칠까지 있는지' 를 뱉는 함수를 만들어봅시다. 

이상한 숫자 넣으면 0을 뱉게 만듭시다. 

(동작예시) 

SELECT 함수(3); 실행하면 31이 출력되어야합니다.

SELECT 함수(2); 실행하면 28이 출력되어야합니다. (윤년은 무시합시다)

SELECT 함수(13); 실행하면 0이 출력되어야합니다. (13월은 이 세계에 없음)

IF() CASE 말고 오늘 배운 IF를 활용합시다. 

 

어떻게 했냐면

 

 

 

DROP FUNCTION IF EXISTS mart.함수;
DELIMITER $$
CREATE FUNCTION mart.함수(구멍 INT)
RETURNS INT
DETERMINISTIC
BEGIN

    IF 구멍 IN (1,3,5,7,8,10,12) THEN 
      RETURN 31;
    ELSEIF 구멍 IN (4,6,9,11) THEN 
      RETURN 30;
    ELSEIF 구멍 = 2 THEN 
      RETURN 28;
    ELSE RETURN 0;
    END IF;

END $$
DELIMITER ; 

OR 연산자를 여러개 쓰기 싫으면 IN 연산자도 있다고 했습니다. 

 

[collapse]

 

 

 

Q2. 파라미터로 '평균'을 입력하면 'card 테이블 사용금액 컬럼'의 평균을 구해주고 

파라미터로 '최댓값'을 입력하면 'card 테이블 사용금액 컬럼'의 최댓값을 구해주고 

파라미터로 '최빈값'을 입력하면 'card 테이블 고객등급 컬럼'의 최빈값의 등장횟수를 구해주는 

procedure를 만들어봅시다. 

최빈값 등장횟수가뭐냐면 그냥 'vip' 라는 문자가 가장 많이 출몰한다면 

'vip' 가 테이블에 몇개 들어있나 출력해달라는 소리입니다. 

 

(동작예시)

CALL 프로시저('평균'); 을 실행하면 245766.6이 출력되어야합니다. (사용금액 평균값임)

CALL 프로시저('최댓값'); 을 실행하면 894000이 출력되어야합니다. (사용금액 최댓값임)

CALL 프로시저('최빈값'); 을 실행하면 6이 출력되어야합니다. (vip가 최빈값이고 그건 6번 출현합니다)

어떻게 했냐면

 

 

DROP PROCEDURE IF EXISTS mart.프로시저;
DELIMITER $$
CREATE PROCEDURE mart.프로시저(구멍 varchar(100))
BEGIN


  IF 구멍 = '평균' THEN
    SELECT AVG(사용금액) FROM mart.card;

  ELSEIF 구멍 = '최댓값' THEN
    SELECT MAX(사용금액) FROM mart.card;

  ELSEIF 구멍 = '최빈값' THEN
    SELECT 고객등급, COUNT(고객등급) FROM mart.card 
    GROUP BY 고객등급 ORDER BY COUNT(고객등급) DESC LIMIT 1;
  END IF;


END
$$ 
DELIMITER ;
CALL mart.프로시저('최댓값');  

 

최빈값은 

GROUP BY로 고객등급을 그룹지어서 DESC 순으로 정렬해봤습니다.

그리고 맨위의 행 1개만 출력하라고 했습니다.