Bibi's DevLog ๐Ÿค“๐ŸŽ

[Codesquad] ์ˆ˜์—… ์ •๋ฆฌ - ์Šคํ† ์–ด๋“œ ํ”„๋กœ์‹œ์ € stored procedure ๋ณธ๋ฌธ

๐Ÿ–ฅ BE ๋ฐฑ์—”๋“œ/Database

[Codesquad] ์ˆ˜์—… ์ •๋ฆฌ - ์Šคํ† ์–ด๋“œ ํ”„๋กœ์‹œ์ € stored procedure

๋น„๋น„ bibi 2021. 6. 2. 23:49

์ˆ˜์—… ์ •๋ฆฌ - ์Šคํ† ์–ด๋“œ ํ”„๋กœ์‹œ์ € stored procedure

๋ชจ๋ฅด๋ฉด ์ด์ƒํ•˜์ง€๋งŒ ๊ตณ์ด ๊ณต๋ถ€ํ•  ํ•„์š”๋Š” ์—†๋Š”..?.. ํ•˜์ง€๋งŒ ์ค‘์š”ํ•œ..!!..

sql ๋ช…๋ น์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์„ ์–ธ์ (declarative) (what) ๋ช…๋ น์ด๋‹ค.

DB์—์„œ '์ ˆ์ฐจ์  ๋ช…๋ น(imperative) (how)'์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์Šคํ† ์–ด๋“œ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

์Šคํ† ์–ด๋“œ ํ”„๋กœ๊ทธ๋žจ

  • DB์— ์ €์žฅ๋œ ํ”„๋กœ๊ทธ๋žจ
  • ํ•œ ๋งˆ๋””๋กœ DB์— ํ”„๋กœ๊ทธ๋žจ์„ ์ €์žฅํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ

์Šคํ† ์–ด๋“œ ํ”„๋กœ์‹œ์ €๋Š” DB์— ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— MySQL ์ข…๋ฃŒ ํ›„ ๋‹ค์‹œ ์‹คํ–‰ํ•ด๋„ ๋‚จ์•„ ์žˆ๋‹ค.

์Šคํ† ์–ด๋“œ ํ”„๋กœ๊ทธ๋žจ์˜ ์ข…๋ฅ˜

  • ์Šคํ† ์–ด๋“œ ํ•จ์ˆ˜
  • ์Šคํ† ์–ด๋“œ ํ”„๋กœ์‹œ์ ธ
  • ํŠธ๋ฆฌ๊ฑฐ
  • ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ

์Šคํ† ์–ด๋“œ ํ”„๋กœ๊ทธ๋žจ์˜ ์žฅ์ 

  • ์‘์šฉํ”„๋กœ๊ทธ๋žจ์˜ ์„ฑ๋Šฅ ํ–ฅ์ƒ
  • ๋„คํŠธ์›Œํฌ ํŠธ๋ž˜ํ”ฝ ๊ฐ์†Œ
    • ์—ฌ๋Ÿฌ ๋ฒˆ ์ฟผ๋ฆฌ ๋‚ ๋ ค์•ผ ํ•˜๋Š” ๊ฑธ ํ•œ ๋ฒˆ์œผ๋กœ ์ค„์ผ ์ˆ˜ ์žˆ์Œ
    • DB์—์„œ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ๊นŒ์ง€ ๋งŒ๋“ค์–ด ๊ทธ๊ฒƒ๋งŒ ๋ณด๋‚ด์ฃผ๊ธฐ ๋•Œ๋ฌธ
  • ๋ณด์•ˆ์„ฑ ํ–ฅ์ƒ
  • ๊ฐœ๋ฐœ ์—…๋ฌด์˜ ๊ตฌ๋ถ„ - ์Šคํ† ์–ด๋“œ ํ”„๋กœ๊ทธ๋žจ์€ DBA๊ฐ€ ์ง ๋‹ค

์Šคํ† ์–ด๋“œ ํ”„๋กœ๊ทธ๋žจ์˜ ๋‹จ์ 

  • ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ๋งค์šฐ ์–ด๋ ต๋‹ค
    • ์ฝ”๋“œ๊ฐ€ DB์— ๋“ค์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ
    • ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ rollback์„ ํ•˜๊ธฐ ์–ด๋ ต๋‹ค
  • git์—์„œ ๊ด€๋ฆฌ๊ฐ€ ์‰ฝ์ง€์•Š๋‹ค
    • DBA๊ฐ€ ๊นƒ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋–„๋ฌธ
  • ๋ช…๋ น ์ž์ฒด์˜ ์„ฑ๋Šฅ ๊ฐ์†Œ (์ž๋ฐ”๋ณด๋‹ค ๋Š๋ฆผ)

์Šคํ† ์–ด๋“œ ํ”„๋กœ๊ทธ๋žจ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ

  • ๊ฒŒ์ž„ ๋ถ„์•ผ์—์„œ ๋งŽ์ด ์‚ฌ์šฉ.
  • ์›น๋ถ„์•ผ๋Š” ์ผ€๋ฐ”์ผ€์ง€๋งŒ ์‚ฌ์šฉ์œจ ๊ฐ์†Œ ์ค‘

stored function vs stored procedure

ํ•จ์ˆ˜๋Š” ์ฟผ๋ฆฌ ๋‚ด์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ. ๋Œ€์‹  ์ œ์•ฝ์‚ฌํ•ญ์ด ๋งŽ์Œ.

ํ”„๋กœ์‹œ์ ธ๋Š” ์ฟผ๋ฆฌ ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ

์šฐ๋ฆฌ๋Š” ํ”„๋กœ์‹œ์ €๋งŒ ๋‹ค๋ฃฌ๋‹ค.

Hello World ์ฐ๊ธฐ

DROP PROCEDURE IF EXISTS SP_HELLO;
DELIMITER $$
CREATE PROCEDURE SP_HELLO()
    BEGIN
        DECLARE STR CHAR(20) DEFAULT 'POPI';
        SET STR = 'HELLO, WORLD';
        SELECT STR;
        END $$
DELIMITER ;

CALL SP_HELLO();
  • SP_... : ๊ด€ํ–‰. ์Šคํ† ์–ด๋“œ ํ”„๋กœ์‹œ์ € ์ด๋ฆ„ ์•ž์— ๋ถ™์ž„

  • DELIMITER $$ : ๊ตฌ๋ถ„์ž. ๊ตฌ๋ฌธ ๋๋‚ด๋Š” ๋ฌธ์žฅ์„ ์‚ฌ์šฉ์ž๊ฐ€ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Œ. (;๋Œ€์‹ )

    • END $$๊นŒ์ง€ $$๋ฅผ ๋ธ๋ฆฌ๋ฏธํ„ฐ๋กœ ์‚ฌ์šฉํ•จ
  • DECLARE STR : STR์ด๋ผ๋Š” ์ด๋ฆ„์˜ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•จ.

    • DB์—์„œ๋Š” ๋ฌธ์ž์—ด์„ ์Œ๋”ฐ์˜ดํ‘œ๊ฐ€ ์•„๋‹Œ ํ™‘๋”ฐ์˜ดํ‘œ'๋กœ ๊ฐ์‹ธ์•ผ ํ•œ๋‹ค!

๊ธฐ๋ณธ ๋ณ€์ˆ˜ ์‚ฌ์šฉํ•˜๊ธฐ

๊ธฐ๋ณธ ๋ณ€์ˆ˜ ์„ ์–ธ : DECLARE ๋ณ€์ˆ˜๋ช… ํƒ€์ž… [DEFAULT ๊ธฐ๋ณธ๊ฐ’]

([]๋‚ด์˜ ๊ฐ’์€ ์˜ต์…˜์ด๋‹ค)

  • ๊ธฐ๋ณธ ๋ณ€์ˆ˜๋Š” ํ”„๋กœ์‹œ์ ธ ๋‚ด์—์„œ๋งŒ ์œ ํšจํ•จ!

์„ธ์…˜ ๋ณ€์ˆ˜ ์„ ์–ธ ๋ฐ ์‚ฌ์šฉ

SET @๋ณ€์ˆ˜๋ช… = ๊ฐ’;

  • ์„ธ์…˜ ๋ณ€์ˆ˜๋Š” ๋ง ๊ทธ๋Œ€๋กœ ์„ธ์…˜ ๋‚ด์—์„œ ๊ณ„์† ์œ ํšจํ•จ.

  • SET @VAR_TEST = 10;

  • SELECT @VAR_TEST;

๊ธฐ๋ณธ ๋ณ€์ˆ˜์— ๊ฐ’ ๋„ฃ๊ธฐ

SET ์‚ฌ์šฉ

SET A = 10;

DROP PROCEDURE IF EXISTS SP_TEST1;
DELIMITER $$
CREATE PROCEDURE SP_TEST1()
    BEGIN
        DECLARE A INT;
        SET A = 10;
        SET A = A * 2;
        SELECT A;
    END $$
DELIMITER ;

CALL SP_TEST1();

SELECT INTO ์‚ฌ์šฉ

์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ณ€์ˆ˜์— ๋„ฃ์„ ์ˆ˜ ์žˆ์Œ.

๋‹จ, ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๊ฐ’์ด ์Šค์นผ๋ผ ๊ฐ’์ด ๊ฒฝ์šฐ๋งŒ ๊ฐ€๋Šฅ

DB์—์„œ ์Šค์นผ๋ผ = ๋‹จ์ผ๊ฐ’์„ ๋œปํ•จ. (ํ…Œ์ด๋ธ” ์—ด ํ•˜๋‚˜๊ฐ€ ์•„๋‹Œ, '๊ฐ’' ํ•˜๋‚˜)

DROP PROCEDURE IF EXISTS SP_TEST2;
DELIMITER $$
CREATE PROCEDURE SP_TEST2()
    BEGIN
        DECLARE A ING;
        SELECT COUNT(UID) INTO A FROM USER_INFO;
        SELECT A;
    END $$
DELIMITER ;

CALL SP_TEST2();

๊ฒฐ๊ณผ๊ฐ’์„ ํ…Œ์ด๋ธ”์— ๋„ฃ๊ธฐ

CREATE TABLE TEST3(NUM INT);
INSERT INTO TEST3 VALUES (1);
DROP PROCEDURE IF EXISTS SP_TEST3;
DELIMITER $$
CREATE PROCEDURE SP_TEST3()
    BEGIN
        DECLARE A INT DEFAULT 1;
        SELECT MAX(NUM) INTO A FROM TEST3;
        SET A = A + 1;
        INSERT INTO TEST3 VALUES(A);
        SELECT * FROM TEST3;
    END $$
DELIMITER ;

CALL SP_TEST3();
CALL SP_TEST3();
CALL SP_TEST3();
SELECT * FROM TEST3;

TEST3 ํ…Œ์ด๋ธ”์—๋Š” 1,2,3,4,5๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค.

๋งค๊ฐœ๋ณ€์ˆ˜ ์‚ฌ์šฉํ•˜๊ธฐ (IN, OUT)

  • IN ๋งค๊ฐœ๋ณ€์ˆ˜๋ช… .

    • ์ž…๋ ฅ์— ์‚ฌ์šฉ

    • DROP TABLE IF EXISTS TEST4;
      CREATE TABLE TEST4 (
          ID INT PRIMARY KEY AUTO_INCREMENT,
          NAME VARCHAR(20)
      );
      INSERT INTO TEST4 VALUES (NULL, 'AA');
      INSERT INTO TEST4 VALUES (NULL, 'BB');
      INSERT INTO TEST4 VALUES (NULL, 'CC');
      INSERT INTO TEST4 VALUES (NULL, 'DD');
      
      DROP PROCEDURE IF EXISTS SP_TEST4;
      DELIMITER $$
      CREATE PROCEDURE SP_TEST4(IN pname varchar(10) )
          BEGIN
              DECLARE A INT DEFAULT 1;
              SELECT * FROM TEST4 WHERE NAME = pname;
          END $$
      DELIMITER ;
      
      CALL SP_TEST4('DD');
    • ๊ฒฐ๊ณผ๋กœ ID๊ฐ€ 4, NAME์ด DD์ธ ๋ฐ์ดํ„ฐ๊ฐ€ ์กฐํšŒ๋œ๋‹ค.

  • OUT ๋งค๊ฐœ๋ณ€์ˆ˜๋ช…

    • ์ถœ๋ ฅ์— ์‚ฌ์šฉ

    • (์ž๋ฐ”์˜ return๊ณผ ๋น„์Šทํ•œ ์šฉ๋„)

    • DROP PROCEDURE IF EXISTS SP_TEST5;
      DELIMITER $$
      CREATE PROCEDURE SP_TEST5(IN pname varchar(10),
          OUT pid int)
          BEGIN
              DECLARE A INT DEFAULT 1;
              SELECT id into pid
                  FROM TEST4
                  WHERE NAME = pname;
          END $$
      DELIMITER ;
      
      CALL SP_TEST5('DD', @var_ret);
      SELECT @VAR_RET;
  • INOUT ๋งค๊ฐœ๋ณ€์ˆ˜๋ช…

    • ์ž…๋ ฅ, ์ถœ๋ ฅ์— ๋™์‹œ์— ์‚ฌ์šฉํ•  ๋ณ€์ˆ˜

IF ์‚ฌ์šฉํ•˜๊ธฐ

END IF;๋กœ ๋๋‚œ๋‹ค๋Š” ์ ์„ ์ฃผ์˜ํ•ด์•ผ.

IF if_expression THEN commands
    [ELSEIF elseif_expression THEN commands]
    [ELSE commands]
    END IF;
DROP TABLE IF EXISTS TEST6;
CREATE TABLE TEST6(NUM INT);

DROP PROCEDURE IF EXISTS SP_TEST6;
DELIMITER $$
CREATE PROCEDURE SP_TEST6(OUT RET INT)
    BEGIN
        DECLARE A INT DEFAULT 1;
        SELECT MAX(NUM) INTO A FROM TEST6;
        IF A IS NULL THEN
            SET A = 1;
        ELSE
            SET A = A + 1;
        END IF;
        INSERT INTO TEST6 VALUES (A);
        SET RET = A;
    END $$
DELIMITER ;

CALL SP_TEST6(@i);
SELECT @i;

CALL SP_TEST6(@i);
SELECT @i;

CALL SP_TEST6(@i);
SELECT @i;

@i์˜ ์ตœ์ข… ๊ฒฐ๊ณผ๊ฐ’ : 3

DB์—์„œ์˜ NULL์€ '๊ฐ’์„ ์ž˜ ๋ชจ๋ฅด๊ฒ ๋‹ค'๋Š” ์˜๋ฏธ์— ๊ฐ€๊น๋‹ค.

NULL + 1 = NULL

WHILE ์‚ฌ์šฉํ•˜๊ธฐ

์—ญ์‹œ END WHILE;๋กœ ๋๋‚œ๋‹ค๋Š” ๊ฒƒ์„ ์กฐ์‹ฌํ•ด์•ผ.

WHILE expression DO
    Statements
END WHILE

๊ธฐํƒ€

์ด ์™ธ์— CASE (switch case์™€ ๊ฐ™์€ ์šฉ๋„), REPEAT_UNTIL(do while๊ณผ ๊ฐ™์€ ์šฉ๋„)๋„ ์žˆ๋‹ค.

์‹ค์Šต1 - DB๋กœ ๋ณ„ ์ฐ๊ธฐ

DROP TABLE IF EXISTS STAR;
CREATE TABLE STAR (LNO INT, LINE VARCHAR(64));

DROP PROCEDURE IF EXISTS SP_STAR;
DELIMITER $$
CREATE PROCEDURE SP_STAR(IN LNO INT)
    BEGIN
        DECLARE S VARCHAR(64) DEFAULT '*';
        DECLARE I INT DEFAULT 1;

        DELETE FROM STAR WHERE LNO >= 1;

        WHILE I <= LNO DO // WHILE๋ฌธ
            INSERT INTO STAR VALUES(I, S);
            SET S = CONCAT(S, '*');
            SET I = I + 1;
        END WHILE;
        SELECT * FROM STAR;
    END $$
DELIMITER ;
  • CONCAT(a, b); : ๋‚ด์žฅํ•จ์ˆ˜. ๋‘ ๋ฌธ์ž์—ด์„ ํ•ฉ์น˜๋Š” ํ•จ์ˆ˜

  • โ—DECLARE๊ฐ€ ์žˆ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ๊ทธ ๊ตฌ๋ฌธ์˜ ๋งจ ์œ„์— ์žˆ์–ด์•ผ ํ•œ๋‹ค.