본문 바로가기

IT/Python

파이썬 executemany 쓰지 않고 한 번에 insert

문제상황: executemany 를 사용하여 insert를 한 번에 처리하고자 함. 

정상작동하던 코드가 insert_dts 컬럼을 추가하고자 하니 문제 발생

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import re 
 
RE_INSERT_VALUES = re.compile(
    r"\s*((?:INSERT|REPLACE)\b.+\bVALUES?\s*)"
    + r"(\(\s*(?:%s|%\(.+\)s)\s*(?:,\s*(?:%s|%\(.+\)s)\s*)*\))"
    + r"(\s*(?:ON DUPLICATE.*)?);?\s*\Z",
    re.IGNORECASE | re.DOTALL,
)
 
query = f'INSERT IGNORE INTO TABLE_NM (aaa, DTS) VALUES (%s, NOW())'
query2 = f'INSERT IGNORE INTO TABLE_NM (aaa) VALUES (%s)'
 
= RE_INSERT_VALUES.match(query)
m2 = RE_INSERT_VALUES.match(query2)
 
cs

 

executemany 를 보면 위와 같이 정규식으로 쿼리를 처리 함. 

정규식에 안 걸림... 

 

https://regexr.com/

정규식 테스트 할 수 있는 사이트

 

<기존코드>

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
31
32
if datas:
        columns = list(datas[0].keys())
        columns_str = ", ".join([f"{col}" for col in columns])
        values_str = ", ".join([f"%({col})s" for col in columns])
        insert_dts = datetime.strftime(datetime.now(timezone("Asia/Seoul")), "%Y-%m-%d %H:%M:%S")
        
        query = f'INSERT IGNORE INTO TABLE_NM ({columns_str}, INSERT_DTS) VALUES ({values_str}, NOW())'
 
        logger.debug(query)
 
        try:
            conn = DB_connection.db_conn()
            cursor = conn.cursor()
 
            cursor.executemany(query, datas)
 
            conn.commit()
 
            result = Result(True)
 
        except MySQLError as err:
            logger.error(f"Database Error occurred: {err}")
            conn.rollback()
            result = Result(False, f"Database Error occurred: {err}")
        
        finally:
            if conn.open:
                cursor.close()
                conn.close()
 
            return result
 
cs

 

<수정코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if datas:
            columns = list(datas[0].keys())
            columns_str = ", ".join([f"{col}" for col in columns] + ["INSERT_DTS"])
 
            values_str = ", ".join(["(" + ", ".join([f"'{data[col]}'" for col in columns] + ["NOW()"]) + ")"for data in datas])
 
            query = f"INSERT IGNORE INTO TABLE_NM ({columns_str}) VALUES\n{values_str}"
 
            logger.debug(query)
 
            try:
                conn = DB_connection.db_conn()
                cursor = conn.cursor()
 
                cursor.execute(query)
 
cs

 

INSERT TABLE(COLUM_NAME) VALUES(DATA), (DATA2),(DATA3) 와 같은 형식으로 쿼리 수정

 

# COULUMNS_STR 에만 INSERT_DTS 를 추가하여야 합니다. COULUMNS 에서 추가하면 VALUES_STR 를 만드는 과정에서 DATAS 에 INSERT_DTS가 없기 때문에 오류가 발생합니다. 

 

참고사항

1. datas 의 형태는 딕셔너리를 리스트로 감싼 형태입니다.