Intro
pymysql은 python에서 mysql 을 사용할 수 있게끔 해주는 라이브러리입니다.
사용법이 쉽고 직관적이며, MySQL의 쿼리 구문을 그대로 사용할 수 있다는 점에서 사용성이 좋은 라이브러리입니다.
더불어 이 라이브러리를 통해 python과 DB간 직접 연결을 할 수 있기 때문에
별도의 중간 통신 방법을 마련하지 않아도 됩니다.
Flow
설치
pip를 통해 pymysql을 설치할 수 있습니다.
1
$ pip install pymysql
기본 사용법
(1) pymysql import
1
import pymysql
(2) DB 연결 객체 생성
1
2
3
4
5
6
7
8
conn = pymysql.connect(
host = "MySQL 서비스의 IP",
port = MySQL 서비스의 포트번호, # int로 입력
user = "DB 계정",
passwd = "계정 비밀번호",
db = "연결할 DataBase",
charset = "DB에서 사용할 인코딩"
)
(3) Cursor 객체 생성
CLI 환경에서 MySQL을 사용한다고 생각해봅시다.
명령어를 작성할 때 깜빡이는 작은 커서가 보이죠?
Cursor 객체는 바로 이 커서를 의미합니다.
1
cursor = conn.cursor()
(4) SQL문 작성 및 실행
cursor.execute() 라는 메서드로 SQL문을 실행시킵니다.
execute : 실행하다.
쉬운 이해를 위해, SELECT로 조회하는 SQL문을 실행해보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cursor.execute("SELECT * FROM test_table;")
# 쿼리가 길어질 경우 아래와 같이 쿼리문 변수 선언을 추천
sql = '''
INSERT INTO table_a (col1, col2, col3)
VALUES (val1, val2, val3)
ON DUPLICATE KEY UPDATE
col1 = val1_b,
col2 = val2_b,
col2 = val3_b
'''
cursor.execute(sql)
(5) SQL문 실행 결과 받아오기
cursor.fetch() 메서드를 통해 받아올 수 있습니다.
해당 메서드는 2중 튜플 형태 ((출력행1-열1값,),(출력행1-열2값,)...(출력행n-열m값))
로 결과값을 받아옵니다.
- fetchall() : 모든 실행결과를 가져온다.
- fetchone() : 실행결과를 한 번에 한 줄씩 가져온다.
- fetchmany(n) : 실행결과를 n줄씩 가져온다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
result = cursor.fetchall()
for i in range(result): # 열 for
for j in range(result[i]): # 행 for
print(result)
>>> 001
>>> 테스트행1
>>> 테스트결과값1
>>> 002
>>> 테스트행2
>>> 테스트결과값2
...
>>> n
>>> 테스트행n
>>> 테스트결과값n
위 코드의 대상인 table은 아래와 같이 생겼습니다.
col1 | col2 | col3 |
---|---|---|
001 | 테스트행1 | 테스트결과값1 |
002 | 테스트행2 | 테스트결과값2 |
… | … | … |
n | 테스트행n | 테스트결과값n |
(6) commit 혹은 rollback
cursor.execute() 를 통해 실행된 내용을 DB에 적용(commit) 하거나 이전 상태로 되돌릴(rollback) 수 있습니다.
commit 이나 rollback은 연결 객체(conn) 단에서 실행합니다.
1
2
3
4
5
# execute 한 명령을 DB에 적용
conn.commit()
# execute 이전 상태로 되돌리기
conn.rollback()
단, 자동 커밋(autocommit) 옵션이 켜져있는 경우엔 rollback이 불가능하니 execute 전 꼭 확인하기를 바랍니다.
1
2
3
4
5
6
7
8
# 자동 커밋 여부 확인
cursor.execute("SHOW VARIABLES LIKE 'AUTOCOMMIT';")
print(cursor.fetchall()[0][0])
>>> 자동커밋 활성화일 경우 : ('autocommit', 'ON')
>>> 자동커밋 비활성화일 경우 : ('autocommit', 'OFF')
# 자동 커밋 변경
cursor.execute("SET autocommit = FALSE;")
(7) 연결 해제
모든 작업을 완료했다면 DB와의 연결을 끊어줍니다.
close 를 하지 않은 연결이 쌓이다 보면 DB의 connection 자원이 고갈되어 연결이 불가능해질 수 있습니다.
1
conn.close()
응용
함께 응용하면 좋을 만한 내용을 몇 가지 적어보겠습니다.
f포매팅
쿼리문의 내용이 항상 고정될 수는 없겠죠?
예를 들어, 여러 행이 있는 엑셀을 DB에 넣는다거나 변화가 많은 변수조건을 적용해야 할 경우 등이 있습니다.
이 경우엔 f포매팅을 이용하면 편합니다.
예를 들어 아래와 같은 표 데이터(pandas)를 DB에 넣는다고 생각해봅시다.
이름 | 최고점 과목 | 점수 |
---|---|---|
김철수 | 영어 | 85 |
이철수 | 수학 | 95 |
남궁철수 | 물리 | 100 |
베르나르철수 | 문학 | 120 |
그러면 아래와 같이 작성이 가능하죠.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
print(df)
>>> |이름|최고점 과목|점수|
>>> |---|---|---|
>>> |김철수|영어|85|
>>> |이철수|수학|95|
>>> |남궁철수|물리|100|
>>> |베르나르철수|문학|120|
for i in range(len(df)):
name = df["이름"].iloc(i)
subj = df["최고점 과목"].iloc(i)
scor = df["점수"].iloc(u)
sql = f'''
INSERT INTO stud_score (name_col, sub_col, sco_col)
VALUES ("{name}", "{subj}", {scor})
ON DUPLICATE KEY UPDATE
sub_col = "{subj}",
sco_col = {scor};
'''
cursor.execute(sql)
% 를 이용한 포매팅도 가능합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
for i in range(len(df)):
name = df["이름"].iloc(i)
subj = df["최고점 과목"].iloc(i)
scor = df["점수"].iloc(u)
sql = f'''
INSERT INTO stud_score (name_col, sub_col, sco_col)
VALUES (%s, %s, %s)
ON DUPLICATE KEY UPDATE
sub_col = %s,
sco_col = %s;
'''
cursor.execute(sql, (name, subj, scor, subj, scor))
f포매팅 주의할 점
그런데 %를 이용한 위 예시에서 이상한 점이 있습니다.
int 형인 “점수” 항목을 넘길 때 숫자를 뜻하는 %d 가 아닌, 문자를 뜻하는 %s로 표현했습니다.
이는 pymysql 에서 주의할 점인데요,
% 포매팅을 할 경우 모든 변수값은 스트링 형태(%s) 로 넘겨야 합니다.
문자든 숫자든 상관 없이요. 그러면 SQL 쪽에서 알맞게 해당 형태를 변환해 입력합니다.
그렇게 하지 않는다면 아래와 같은 오류를 볼 수 있습니다.
1
>>> %d format: a number is required, not str
pymysql에서 %포매팅을 할 때에는 무조건 문자열 형태(%s) 로 넘기자!
null 값 넣기
특정 부분에 값이 없는 경우, SQL에서는 (null) 로 표시가 됩니다.
DB에 null 값을 pymysql을 통해 넣으려면?
None
값을 이용하면 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
if isinstance(df["val_a"].iloc[i]) == True:
val_a = df["val_a"].iloc[i]
else:
val_a = None
sql = f'''
INSERT INTO (col1)
VALUES %s
'''
cursor.execute(sql, (val_a))
가능한 쿼리문
위 예시에서는 SELECT, INSERT 와 같은 간단한 구문만을 예시로 들었습니다.
하지만 CREATE, GRANT 등의 명령어 또한 실행이 가능합니다.
python에서 MySQL을 사용한다고 생각하고 쓰시면 됩니다.
python에서 편리하게 MySQL을 사용할 수 있게 해주는 pymysql.
데이터를 다루는 입장에서는 꼭 알아야 할 필요가 있습니다.
여기까지 pymysql에 대한 설명이었습니다.
감사합니다.
Reference
- pymysql 기본 사용법 : https://pymysql.readthedocs.io/en/latest/
- pymysql 기본 사용법 : https://www.fun-coding.org
- pymysql 기본 사용법 : https://velog.io/@c_hyun403/SQL-PyMySql
- %포매팅 오류 : https://timmer.tistory.com/135
- autocommit : https://loklee9.tistory.com/153
- autocommit : https://zetawiki.com
- fetch : http://pythonstudy.xyz