본문 바로가기
Study

[SQL] Chapter 4. (9~11강)

by Hwanin99 2025. 7. 7.

9강.

변수 생성

SET @myvar1 = 5;
SET @myvar2 = 4.25;

SELECT @myvar1 + @myvar2
출력 결과

 

SET @txt = '가수 이름==>';
SET @height = 166;

SELECT @txt, mem_name FROM member WHERE height > @height;
출력 결과
  • member 테이블의 height가 @height보다 mem_name을 @txt와 같이 출력.

 

SET @count = 3;
SELECT mem_name, height
FROM member
ORDER BY height
LIMIT @count;  # 오류 발생
--------------------------
SET @count = 3;
PREPARE pre_name 
FROM 'SELECT mem_name, height
      FROM member
      ORDER BY height
      LIMIT ?';
EXECUTE pre_name USING @count
출력 결과
  • LIMIT은 compile time에 값이 정적으로 확정되어야 쿼리를 최적화할 수 있다.
    • 그러나, @count는 runtime 변수이기에, 정적으로 판단을 못함.
    • 이를 해결하기 위해, 'PREPARE + EXECUTE'를 사용한 동적 쿼리 방식으로 처리.

정수 변환

SELECT AVG(price) '평균 가격' FROM buy
출력 결과

 

SELECT CAST(AVG(price) AS SIGNED) '평균 가격' FROM buy;

#위와 아래 둘 다 동일

SELECT CONVERT(AVG(price), SIGNED) '평균 가격' FROM buy
출력 결과

문자와 숫자를 섞어 사용

SELECT num, CONCAT(CAST(price AS CHAR), 'X', CAST(amount AS CHAR), '=') '가격x수량', price*amount
FROM buy
출력 결과
  • 강의에서는 price, 'X', amount, '='를 합치기 위해서 price와 amount를 문자로 변환해야 한다고 나온다.
    • 아래와 같이 문자로 변환하지 않아도 결과는 똑같은 것을 확인했으나, 만일을 대비해서 변환하는 것을 습관들이는 것이 좋을 것 같다.
SELECT num, CONCAT(price, 'X', amount, '=') '가격x수량', price*amount '구매액'
FROM buy

10강.

JOIN

JOIN 종류

INNER JOIN

  • 두 테이블을 연결할 때 가장 많이 사용된다.
    • 일반적으로 그냥 join이라고 하면, 내부 조인을 뜻함.

  • 위와 같이 member 테이블과 buy 테이블이 있다고 했을 때, 두 테이블의 연결고리는 member_id이다.
  • INNER JOIN을 하게 되면, member_id를 기준으로 교집합의 행만을 join한다.

 

SELECT *
FROM buy
INNER JOIN member
ON buy.member_id = member.member_id
출력 결과
  • 결과를 보면, 교집합이 아닌 'iyou', 'yg'는 가져오지 않는다.
  • buy와 member 모두에 member_id 컬럼이 있기에, 중복되어 출력된다.
    • 따로 지정하여 SELECT하면 됨.

 

SELECT member_id, product_name, price, member_name, member_addr, height
FROM buy
INNER JOIN member
ON buy.member_id = member.member_id  #오류 발생
----------------------------------------------------------------------------
SELECT buy.member_id, product_name, price, member_name, member_addr, height
FROM buy
INNER JOIN member
ON buy.member_id = member.member_id
출력 결과
  • 위에서 말했듯 member_id는 두 테이블에 모두에 있기에, 어떤 테이블의 컬럼인지 지정해줘야 함.

 

SELECT B.member_id, B.product_name, B.price, M.member_name, M.member_addr, M.height
FROM buy B
INNER JOIN member M
ON B.member_id = M.member_id
  • buy는 B, member는 M으로 별명을 줘서 사용도 가능하다.

OUTER JOIN

  • 두 테이블에 모두 데이터가 있어야만 결과가 나오는 내부 조인과 달리, 외부 조인은 한쪽에만 데이터가 있어도 결과가 나온다.
# LEFT OUTER JOIN
SELECT B.member_id, B.product_name, B.price, M.member_name, M.member_addr, M.height
FROM buy B
LEFT OUTER JOIN member M
ON B.member_id = M.member_id
-----------------------------------------------------------------------------------
# RIGHT OUTER JOIN
SELECT B.member_id, B.product_name, B.price, M.member_name, M.member_addr, M.height
FROM buy B
RIGHT OUTER JOIN member M
ON B.member_id = M.member_id
출력 결과

↑ LEFT JOIN ↑


↑ RIGHT JOIN ↑
  • LEFT와 RIGHT는 위치만 다르지 결과는 같은 것을 볼 수 있다.

CROSS JOIN

  • 내부 조인이나 외부 조인처럼 자주 사용되지는 않지만, 가끔 유용하게 사용되는 조인이다.
    • 내용적 의미는 없으나, 대용량의 데이터를 생성할 때 사용한다.
SELECT *
FROM buy
CROSS JOIN member
출력 결과

11강.

STORED PROCEDURE

  • 어떠한 동작을 일괄 처리하기 위한 용도이다.
  • 쿼리문 처리를 바로 처리하지 않고 값을 받아와 프로시저 내부에서 일괄적으로 처리하 후 결과를 보내주기 위한 루틴이다.


IF문

  • 프로그래밍에서 사용하는 IF문과 동일하다.

 

DELIMITER $$
CREATE PROCEDURE ifProc1()
BEGIN
	IF 100 = 100 THEN
    	SELECT '100은 100과 같습니다.' ;
    END IF ;
END $$
DELIMITER ;
CALL ifProc1() ;
출력 결과
  • 100=100을 만족하므로 '100dms 100과 같습니다.'를 출력.
    • '100=100이 아닌 숫자'인 경우에는 아무것도 출력하지 않는다.

IF ~ ELSE문

DELIMITER $$
CREATE PROCEDURE ifProc2()
BEGIN
	DECLARE myNum INT ;
    SET myNum = 200 ;
    IF myNum = 100 THEN
    	SELECT '100입니다.' ;
    ELSE
    	SELECT '100이 아닙니다.' ;
    END IF ;
END $$
DELIMITER ;
CALL ifProc2() ;
출력 결과

CASE문

  • IF문은 참과 거짓 2가지(2중 분기)이지만, CASE문은 2가지 이상의 경우(다중 분기)일 때 처리가 가능하다.

 

DELIMITER $$
CREATE PROCEDURE caseProc()
BEGIN
    DECLARE point INT ;
    DECLARE credit CHAR(1) ;
    SET point = 88 ;
    
    CASE 
        WHEN point >= 90 THEN
            SET credit = 'A' ;
        WHEN point >= 80 THEN
            SET credit = 'B' ;
        WHEN point >= 70 THEN
            SET credit = 'C' ;
        WHEN point >= 60 THEN
            SET credit = 'D' ;
        ELSE
            SET credit = 'F' ;
    END CASE ;
    SELECT CONCAT('취득점수==>', point), CONCAT('학점==>', credit) ;
END $$
DELIMITER ;
CALL caseProc() ;
출력 결과

WHILE문

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 ;    #hap의 원래의 값에 i를 더해서 다시 hap에 넣으라는 의미
        SET i = i + 1 ;      #i의 원래의 값에 1을 더해서 다시 i에 넣으라는 의미
    END WHILE ;

    SELECT '1부터 100까지의 합 ==>', hap ;   
END $$
DELIMITER ;
CALL whileProc() ;
출력 결과
  • 1~100까지의 합

 

DELIMITER $$
CREATE PROCEDURE whileProc2()
BEGIN
    DECLARE i INT ;    #1에서 100까지 증가할 변수
    DECLARE hap INT ;    #더한 값을 누적할 변수
    SET i = 1 ;
    SET hap = 0 ;

    myWhile: 
    WHILE (i <= 100) DO     #While문에 label을 지정
       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() ;
출력 결과
  • 1~100까지의 합(4의 배수 제외), 1000 넘으면 종료

동적 SQL

PREPARE & EXECUTE

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 ;
출력 결과