Sql

mysql 프로시저 활용하기

hojomu 2023. 9. 7. 08:16

데이터를 (),(),(); 형태로 만들었고, insert하기 위한 프로시저를 실행시켰다

 

프로시저를 활용하는 이유 : insert / update 는 실행 중 일때 데이터의 안정성을 위해 해당 작업이 끝날 때 까지 다른 작업을 시작하지 않는다. 그렇기 때문에 실제로 운영하는 서버에서는 insert,update를 수행하는 시간을 매우짧게 가져가야한다.

여기서는 배열 형태의 데이터를 임시테이블에 저장해뒀다가 insert 시키기 위해 프로시저를 활용했다.

CREATE DEFINER=`host` PROCEDURE `DataInsert`(
	IN `input_string` TEXT,
	IN `standardDate` INT
)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
    -- Create the temporary table
    CREATE TEMPORARY TABLE IF NOT EXISTS TEMPTABLE (
        ID INT,
        DATE INT,
        VALUE DECIMAL(12, 4),
        STANDARD_DATE INT
    );
    
    -- Load data from input_string into TEMPTABLE using INSERT INTO ... VALUES
    SET @insert_query = CONCAT(
        "INSERT INTO TEMPTABLE (ID, DATE, VALUE) VALUES ",
        input_string
    );
    PREPARE insert_stmt FROM @insert_query;
    EXECUTE insert_stmt;
    DEALLOCATE PREPARE insert_stmt;
    
    UPDATE TEMPTABLE SET STANDARD = standardDate;
    
    -- Process the data and insert into PRICE table
    INSERT INTO PRICE (ID, DATE, VALUE, STANDARD)
    SELECT t.ID, t.DATE, t.VALUE, t.STANDARD
    FROM TEMPTABLE t
    LEFT JOIN (
        SELECT p.ID, MAX(p.DATE) AS DATE
        FROM PRICE p
        WHERE p.DBSTATUS = 'A'
        GROUP BY p.ID
    ) p ON t.ID = p.ID AND t.DATE <= p.DATE
    WHERE p.ID IS NULL;
    
    UPDATE stock_error_log sel
    JOIN TEMPTABLE t ON sel.ID = t.ID
    SET sel.STATUS = 'D';
    
    -- Clean up: Drop the temporary table
    DROP TEMPORARY TABLE IF EXISTS TEMPTABLE;
    
END

프로시저를 생성하면, BEGIN과 END 사이에 수행하고자 하는 쿼리문을 작성하면 된다

CREATE DEFINER=`host` PROCEDURE `DataInsert`(
	IN `input_string` TEXT,
	IN `standardDate` INT
)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN

쿼리문

END

 

이 프로시저를 시작하기 전에, 쿼리문에 사용할 데이터를 string 형태로 만들어 뒀기 때문에

프로시저 내부에서 반복문을 사용하지 않고 JSON형태의 데이터로 임시 테이블을 작성할 수 있다.

 

프로시저 내부에서는 단순한 CURD 명령어만 수행하고 반복, 조건문 등의 명령을 자제하도록 하자.

 

CREATE TEMPORARY TABLE IF NOT EXISTS TEMPTABLE (
        ID INT,
        DATE INT,
        VALUE DECIMAL(12, 4),
        STANDARD_DATE INT
    );
    
-- Load data from input_string into TEMPTABLE using INSERT INTO ... VALUES
SET @insert_query = CONCAT(
    "INSERT INTO TEMPTABLE (ID, DATE, VALUE) VALUES ",
    input_string
);
PREPARE insert_stmt FROM @insert_query;
EXECUTE insert_stmt;
DEALLOCATE PREPARE insert_stmt;

임시 테이블을 CREATE 한 뒤,

SET 을 사용해서 사용자 정의 변수 내부에 실행할 쿼리문( @insert_query )을 저장한다.

PREPARE 로 @insert_query에 저장된 쿼리문을 실행할 수 있도록 컴파일하고 저장한다.

EXECUTE 를 통해 컴파일된 쿼리문을 실행한다.

DEALLOCATE PREPARE 을 이용해서 저장되어있는 컴파일 실행문을  삭제한다.

 

INSERT INTO PRICE (ID, DATE, VALUE, STANDARD)
    SELECT t.ID, t.DATE, t.VALUE, t.STANDARD
    FROM TEMPTABLE t
    LEFT JOIN (
        SELECT p.ID, MAX(p.DATE) AS DATE
        FROM PRICE p
        WHERE p.DBSTATUS = 'A'
        GROUP BY p.ID
    ) p ON t.ID = p.ID AND t.DATE <= p.DATE
    WHERE p.ID IS NULL;

LEFT JOIN 과 WHERE p.ID IS NULL 을 활용해서 기존의 테이블과 임시테이블을 비교해서 기존 테이블에 이미 들어가있는 데이터는 제외하고 새로운 데이터만 저장되도록 한다.

 

DROP TEMPORARY TABLE IF EXISTS TEMPTABLE;

마지막으로 메모리에 올라가있는 임시 테이블을 삭제한다. IF문을 사용하지 않아도 무방하다.