Python MySQL ์ฐ๋ (PyMySQL CRUD)
๐ PyMySQL์ ์ด์ฉํ์ฌ Python๊ณผ MySQL์ ์ฐ๋ํ๋ ๋ฐฉ๋ฒ์ ์ ๋ฆฌํ๋ค. Connection๊ณผ Cursor์ ์ญํ ๋ถํฐ CRUD ๊ตฌํ, ํธ๋์ญ์ ์ฒ๋ฆฌ, ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ, SQL Injection ๋ฐฉ์ง๊น์ง ํจ๊ป ์ดํด๋ณธ๋ค.
๐ฏ ํ์ต ๋ชฉํ
Python ํ๋ก๊ทธ๋จ์์ MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ ๋ฆฌํ๋ค.
PyMySQL ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐํ๊ณ , SQL์ ์คํํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์กฐํ(Read), ์ฝ์ (Create), ์์ (Update), ์ญ์ (Delete)ํ๋ ๊ธฐ๋ณธ์ ์ธ CRUD ์์ ์ ๊ตฌํํด๋ณธ๋ค.
๋ํ ํธ๋์ญ์ ์ฒ๋ฆฌ์ ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ์ ํจ๊ป ์ดํด๋ณด๋ฉฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์์ ํ๊ฒ ์ฌ์ฉํ๋ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ๋ ํจ๊ป ์ตํ๋ณธ๋ค.
์ด๋ฒ ํฌ์คํ ์์ ๋ค๋ฃจ๋ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ๋ค.
- PyMySQL์ ์ด์ฉํ MySQL ์ฐ๊ฒฐ
- Connection๊ณผ Cursor์ ์ญํ
- CRUD ๊ตฌํ ๋ฐฉ๋ฒ
commit()๊ณผrollback()์ ์ด์ฉํ ํธ๋์ญ์ ์ฒ๋ฆฌ- SQL Injection์ ๋ฐฉ์งํ๋ ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ
๐ ๏ธ ์ฌ์ ์ค๋น
Python์์ MySQL์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๊ทผํ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ ์คํธ๋ฅผ ์ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ๊ฒฝ์ด ์ค๋น๋์ด ์์ด์ผ ํ๋ค.
์ด๋ฒ ํฌ์คํ
์์๋ PyMySQL ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉฐ, ์์ ๋ ๋ก์ปฌ ํ๊ฒฝ์์ ์คํ๋๋ MySQL์ ๊ธฐ์ค์ผ๋ก ์งํํ๋ค.
PyMySQL ์ค์น
pip ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์ฌ PyMySQL์ ์ค์นํ๋ค.
1
pip install pymysql
์ค์น๊ฐ ์๋ฃ๋๋ฉด Python์์ ๋ค์๊ณผ ๊ฐ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ถ๋ฌ์ฌ ์ ์๋ค.
1
import pymysql
์ค์ต ํ๊ฒฝ
์์ ๋ฅผ ์คํํ๊ธฐ ์ํด์๋ MySQL ์๋ฒ๊ฐ ์คํ ์ค์ด์ด์ผ ํ๋ฉฐ, ์ฌ์ฉํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ์ด๋ธ์ด ๋ฏธ๋ฆฌ ์์ฑ๋์ด ์์ด์ผ ํ๋ค.
์ด๋ฒ ์์ ์์๋ ๋ค์๊ณผ ๊ฐ์ emp ํ
์ด๋ธ์ ๊ธฐ์ค์ผ๋ก CRUD๋ฅผ ๊ตฌํํ๋ค.
| ์ปฌ๋ผ๋ช | ๋ฐ์ดํฐ ํ์ | ์ค๋ช |
|---|---|---|
empno |
INT |
์ฌ์๋ฒํธ (Primary Key) |
ename |
VARCHAR(20) |
์ฌ์๋ช |
job |
VARCHAR(20) |
์ง๊ธ |
hiredate |
DATE |
์ ์ฌ์ผ |
sal |
DECIMAL(10,2) |
๊ธ์ฌ |
deptno |
INT |
๋ถ์๋ฒํธ |
-
์ํ ๋ฐ์ดํฐ ์ค๋น
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
CREATE DATABASE IF NOT EXISTS company; USE company; CREATE TABLE emp ( empno INT PRIMARY KEY COMMENT '์ฌ์๋ฒํธ', ename VARCHAR(20) NOT NULL COMMENT '์ฌ์๋ช ', job VARCHAR(20) COMMENT '์ง๊ธ', hiredate DATE COMMENT '์ ์ฌ์ผ', sal DECIMAL(10,2) COMMENT '๊ธ์ฌ', deptno INT COMMENT '๋ถ์๋ฒํธ' ); INSERT INTO emp (empno, ename, job, hiredate, sal, deptno) VALUES (1001, 'KIM', 'DEVELOPER', '2022-03-01', 3800000, 10), (1002, 'LEE', 'DEVELOPER', '2021-07-15', 4200000, 10), (1003, 'PARK', 'MANAGER', '2019-05-20', 5500000, 10), (1004, 'CHOI', 'ANALYST', '2023-01-10', 3600000, 20), (1005, 'JUNG', 'DEVELOPER', '2022-09-05', 4100000, 20), (1006, 'HAN', 'MANAGER', '2018-11-01', 6200000, 20), (1007, 'YOON', 'SALESMAN', '2021-12-20', 3300000, 30), (1008, 'LIM', 'SALESMAN', '2020-08-18', 3500000, 30), (1009, 'KANG', 'ANALYST', '2019-04-12', 4700000, 30), (1010, 'SHIN', 'DIRECTOR', '2017-02-01', 7800000, 40);
์ด๋ฒ ํฌ์คํ ์์ ์ฌ์ฉํ๋ ํ๊ฒฝ์ ๋ค์๊ณผ ๊ฐ๋ค.
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| Language | Python 3.x |
| Database | MySQL 8.x |
๐ PyMySQL ๊ธฐ๋ณธ ๊ฐ๋
PyMySQL์ Python์์ MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํต์ ํ๊ธฐ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
Python์ด ์ง์ MySQL ์๋ฒ์ ํต์ ํ๋ ๊ฒ์ด ์๋๋ผ, PyMySQL์ด SQL์ ์ ๋ฌํ๊ณ ์คํ ๊ฒฐ๊ณผ๋ฅผ Python ๊ฐ์ฒด ํํ๋ก ๋ณํํ์ฌ ๋ฐํํ๋ ์ญํ ์ ์ํํ๋ค.
๋ฐ๋ผ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ๋จ์ํ SQL์ ์คํํ๋ ๊ฒ์์ ๋๋๋ ๊ฒ์ด ์๋๋ผ, Connection์ ์์ฑํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐํ๊ณ , Cursor๋ฅผ ํตํด SQL์ ์คํํ ๋ค, ํ์ํ ๊ฒฝ์ฐ ํธ๋์ญ์ ์ ์ฒ๋ฆฌํ๊ณ ์ฐ๊ฒฐ์ ์ข ๋ฃํ๋ ์์๋ก ์ด๋ฃจ์ด์ง๋ค.
์ด๋ฌํ ๊ธฐ๋ณธ ๋์ ๊ณผ์ ์ ์ดํดํ๋ฉด ์ดํ์ ๋ค๋ฃฐ CRUD ๊ตฌํ๊ณผ ์์ธ ์ฒ๋ฆฌ๋ ๋์ฑ ์ฝ๊ฒ ์ดํดํ ์ ์๋ค.
๐ Connection ๊ฐ์ฒด : ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ
Connection ๊ฐ์ฒด๋ Python ํ๋ก๊ทธ๋จ๊ณผ MySQL ์๋ฒ๋ฅผ ์ฐ๊ฒฐํ๋ ์ญํ ์ ํ๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๊ทผํ๊ธฐ ์ํด ๊ฐ์ฅ ๋จผ์ ์์ฑํด์ผ ํ๋ ๊ฐ์ฒด์ด๋ฉฐ, ์ ์ ์ ๋ณด(ํธ์คํธ, ์ฌ์ฉ์, ๋น๋ฐ๋ฒํธ, ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ช ๋ฑ)๋ฅผ ์ด์ฉํ์ฌ ์์ฑํ๋ค.
1
2
3
4
5
6
7
8
9
import pymysql
conn = pymysql.connect(
host="DB_HOST", # ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ฒ ์ฃผ์
user="DB_USER", # ์ฌ์ฉ์ ๊ณ์
password="DB_PASSWORD", # ๋น๋ฐ๋ฒํธ
database="DB_NAME", # ์ฌ์ฉํ ๋ฐ์ดํฐ๋ฒ ์ด์ค
charset="utf8mb4" # ๋ฌธ์ ์ธ์ฝ๋ฉ
)
Connection์ด ์์ฑ๋๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํต์ ํ ์ค๋น๊ฐ ์๋ฃ๋๋ค.
๐ Cursor ๊ฐ์ฒด : SQL ์คํ
Connection ๊ฐ์ฒด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ๊ด๋ฆฌํ๋ฉฐ, SQL ์คํ์ Cursor ๊ฐ์ฒด๋ฅผ ํตํด ์ํํ๋ค.
1
cursor = conn.cursor()
Cursor๋ SQL์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๋ฌํ๊ณ , ์คํ ๊ฒฐ๊ณผ๋ฅผ Python์ผ๋ก ๊ฐ์ ธ์ค๋ ์ญํ ์ ์ํํ๋ค.
๐ SQL ์คํ ๊ณผ์
PyMySQL์ ์ด์ฉํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ๋๋ถ๋ถ ์๋์ ๊ฐ์ ์์๋ก ์งํ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
1. Connection ์์ฑ
โ
2. Cursor ์์ฑ
โ
3. SQL ์คํ (execute)
โ
4. ๊ฒฐ๊ณผ ์กฐํ (fetch)
โ
5. ํธ๋์ญ์
์ฒ๋ฆฌ (commit / rollback)
โ
6. Cursor ์ข
๋ฃ
โ
7. Connection ์ข
๋ฃ
์กฐํ(SELECT)๋ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ณผ์ ์ด ์ถ๊ฐ๋๊ณ , ์ฝ์ ยท์์ ยท์ญ์ (INSERT/UPDATE/DELETE)๋ ํธ๋์ญ์ ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค.
๐ execute() : SQL ์คํ
SQL์ ์คํํ ๋๋ execute() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค.
1
2
3
sql = "SELECT * FROM emp"
cursor.execute(sql)
SQL๋ฌธ์ ๊ฐ์ ์ ๋ฌํ ๋๋ ๋ฌธ์์ด์ ์ง์ ์ฐ๊ฒฐํ์ง ์๊ณ ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค.
1
2
3
sql = "SELECT * FROM emp WHERE deptno = %s"
cursor.execute(sql, (10,))
%s๋ ์ ๋ฌํ ๊ฐ์ ์๋ฏธํ๋ฉฐ, execute()์ ๋ ๋ฒ์งธ ์ธ์๋ ํํ(tuple) ๋๋ ๋ฆฌ์คํธ(list) ํํ๋ก ์ ๋ฌํ๋ค.
์ฐธ๊ณ : ๊ฐ์ด ํ๋์ธ ๊ฒฝ์ฐ์๋
(10,)๊ณผ ๊ฐ์ด ํํ ํํ๋ก ์์ฑํด์ผ ํ๋ค.
๐ fetch() ๋ฉ์๋ : ์กฐํ ๊ฒฐ๊ณผ ๊ฐ์ ธ์ค๊ธฐ
์กฐํ ๊ฒฐ๊ณผ๋ ํ์์ ๋ฐ๋ผ ์ฌ๋ฌ ๊ฐ์ง ๋ฉ์๋๋ก ๊ฐ์ ธ์ฌ ์ ์๋ค.
| ๋ฉ์๋ | ์ค๋ช |
|---|---|
fetchone() |
ํ ๊ฐ์ ํ ๋ฐํ |
fetchmany(n) |
์ง์ ํ ๊ฐ์๋งํผ ๋ฐํ |
fetchall() |
๋ชจ๋ ํ ๋ฐํ |
์๋ฅผ ๋ค์ด ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์๋ค.
1
2
3
4
5
6
cursor.execute("SELECT * FROM emp")
rows = cursor.fetchall()
for row in rows:
print(row)
๐ commit()๊ณผ rollback() : ํธ๋์ญ์
์ฒ๋ฆฌ
PyMySQL์ ๊ธฐ๋ณธ์ ์ผ๋ก autocommit์ด ๋นํ์ฑํ๋์ด ์์ผ๋ฏ๋ก INSERT, UPDATE, DELETE ์ดํ์๋ commit()์ ํธ์ถํด์ผ ๋ณ๊ฒฝ ์ฌํญ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์๋๋ค.
๋ณ๊ฒฝ ๋ด์ฉ์ ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์ํ๋ ค๋ฉด commit()์ ํธ์ถํด์ผ ํ๋ค.
1
conn.commit()
์์
๋์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค๋ฉด rollback()์ผ๋ก ์ด์ ์ํ๋ก ๋๋๋ฆด ์ ์๋ค.
1
conn.rollback()
ํธ๋์ญ์ ์ฒ๋ฆฌ๋ฅผ ํตํด ๋ฐ์ดํฐ์ ์ผ๊ด์ฑ์ ์ ์งํ ์ ์์ผ๋ฉฐ, ์ค๋ฌด์์๋ ๋ฐ๋์ ์ฌ์ฉ๋๋ ๊ธฐ๋ฅ์ด๋ค.
๐ close() : ์ฐ๊ฒฐ ์ข
๋ฃ
์ฌ์ฉ์ด ๋๋ Connection๊ณผ Cursor๋ ๋ฐ๋์ ์ข ๋ฃํ๋ ๊ฒ์ด ์ข๋ค.
1
2
cursor.close()
conn.close()
์ฌ์ฉํ์ง ์๋ ๊ฐ์ฒด๋ฅผ ๊ณ์ ์ ์งํ๋ฉด ๋ถํ์ํ๊ฒ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ด ์ ์ ๋ ์ ์์ผ๋ฏ๋ก, ์์ ์ด ๋๋ ํ์๋ ํญ์ ์ข ๋ฃํ๋ ์ต๊ด์ ๋ค์ด๋ ๊ฒ์ด ์ข๋ค.
๐งฉ DB ์ฐ๊ฒฐ
์์ผ๋ก ์์ฑํ CRUD ํจ์์์๋ ๋ชจ๋ ๋์ผํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ํด์ผ ํ๋ค.
๋งค๋ฒ pymysql.connect()๋ฅผ ๋ฐ๋ณตํด์ ์์ฑํ๋ ๋์ , ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ๋ฐํํ๋ ํจ์๋ฅผ ํ๋ ๋ง๋ค์ด๋๋ฉด ์ฝ๋์ ์ค๋ณต์ ์ค์ผ ์ ์๋ค.
๐ DB ์ฐ๊ฒฐ ํจ์
1
2
3
4
5
6
7
8
9
10
import pymysql
def get_connection():
return pymysql.connect(
host="host", # ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ฒ ์ฃผ์
user="user", # ์ฌ์ฉ์ ๊ณ์
password="password", # ์ฌ์ฉ์ ๋น๋ฐ๋ฒํธ
database="company", # ์ฐ๊ฒฐํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ด๋ฆ
charset="utf8mb4" # ๋ฌธ์ ์ธ์ฝ๋ฉ
)
get_connection()์ ํธ์ถํ๋ฉด Connection ๊ฐ์ฒด๊ฐ ๋ฐํ๋๋ฉฐ, ์ดํ CRUD ํจ์์์๋ ์ด ๊ฐ์ฒด๋ฅผ ์ด์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์
์ ์ํํ๋ค.
๐ Connection๊ณผ Cursor ์์ฑ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์์
์ ์์ํ ๋๋ ๋จผ์ Connection์ ์์ฑํ๊ณ , ๊ทธ ๋ค์ Cursor๋ฅผ ์์ฑํ๋ค.
1
2
conn = get_connection()
cursor = conn.cursor()
Connection: ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐ์ ๊ด๋ฆฌํ๋ ๊ฐ์ฒดCursor: SQL์ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฐ์ฒด
์ด ๋ ๊ฐ์ฒด๋ ๋๋ถ๋ถ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์์ ํญ์ ํจ๊ป ์ฌ์ฉ๋๋ค.
๐ CRUD์์์ ๊ณตํต ๊ตฌ์กฐ
์์ผ๋ก ์์ฑํ ๋ชจ๋ ํจ์๋ ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
def function_name():
conn = get_connection()
cursor = conn.cursor()
try:
# SQL ์คํ
finally:
cursor.close()
conn.close()
์กฐํ๋ฟ๋ง ์๋๋ผ ์ฝ์
, ์์ , ์ญ์ ์ญ์ ๊ฐ์ ํ๋ฆ์ผ๋ก ์์ฑํ ์ ์์ผ๋ฉฐ, finally์์ Cursor์ Connection์ ์ข
๋ฃํ๋ฉด ์์ธ๊ฐ ๋ฐ์ํ๋๋ผ๋ ์ฐ๊ฒฐ์ด ์ ์์ ์ผ๋ก ์ ๋ฆฌ๋๋ค.
๐ READ (์กฐํ)
PyMySQL์์๋ SELECT ๋ฌธ์ ์คํํ ํ fetchone(), fetchmany(), fetchall() ๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ ์กฐํ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค.
๐ ๊ธฐ๋ณธ ์์ฑ ํฌ๋งท
PyMySQL์ ์ฌ์ฉํ ์กฐํ ํจ์๋ ๋ณดํต ๋ค์ ํ๋ฆ์ผ๋ก ์์ฑํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def ํจ์๋ช
():
conn = get_connection()
cursor = conn.cursor()
try:
sql = """
SELECT ์ปฌ๋ผ๋ช
FROM ํ
์ด๋ธ๋ช
WHERE ์กฐ๊ฑด
"""
cursor.execute(sql, ๊ฐ)
rows = cursor.fetchall()
for row in rows:
print(row)
finally:
cursor.close()
conn.close()
SELECT๋ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ์ง ์์ผ๋ฏ๋ก commit()์ด ํ์ํ์ง ์๋ค.
โจ๏ธ ์์ : ์ ์ฒด ์ฌ์ ์กฐํ
emp ํ
์ด๋ธ์ ๋ชจ๋ ์ฌ์์ ์กฐํํ๋ ํจ์์ด๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def select_all_emp():
conn = get_connection()
cursor = conn.cursor()
try:
sql = """
SELECT empno, ename, job, hiredate, sal, deptno
FROM emp
ORDER BY empno
"""
cursor.execute(sql)
rows = cursor.fetchall()
for row in rows:
print(row)
finally:
cursor.close()
conn.close()
- โบ ์ฌ์ฉ ์์์ ์คํ ๊ฒฐ๊ณผ
1
select_all_emp()
1 2 3 4 5 6 7 8 9 10
(1001, 'KIM', 'DEVELOPER', datetime.date(2022, 3, 1), Decimal('3800000.00'), 10) (1002, 'LEE', 'DEVELOPER', datetime.date(2021, 7, 15), Decimal('4200000.00'), 10) (1003, 'PARK', 'MANAGER', datetime.date(2019, 5, 20), Decimal('5500000.00'), 10) (1004, 'CHOI', 'ANALYST', datetime.date(2023, 1, 10), Decimal('3600000.00'), 20) (1005, 'JUNG', 'DEVELOPER', datetime.date(2022, 9, 5), Decimal('4100000.00'), 20) (1006, 'HAN', 'MANAGER', datetime.date(2018, 11, 1), Decimal('6200000.00'), 20) (1007, 'YOON', 'SALESMAN', datetime.date(2021, 12, 20), Decimal('3300000.00'), 30) (1008, 'LIM', 'SALESMAN', datetime.date(2020, 8, 18), Decimal('3500000.00'), 30) (1009, 'KANG', 'ANALYST', datetime.date(2019, 4, 12), Decimal('4700000.00'), 30) (1010, 'SHIN', 'DIRECTOR', datetime.date(2017, 2, 1), Decimal('7800000.00'), 40)
โจ๏ธ ์์ : ์กฐ๊ฑด ์กฐํ
ํน์ ๋ถ์์ ์ฌ์๋ง ์กฐํํ๋ ค๋ฉด WHERE ์ ์ ์ฌ์ฉํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def select_emp_by_deptno(deptno):
conn = get_connection()
cursor = conn.cursor()
try:
sql = """
SELECT empno, ename, job, hiredate, sal, deptno
FROM emp
WHERE deptno = %s
ORDER BY empno
"""
cursor.execute(sql, (deptno,))
rows = cursor.fetchall()
for row in rows:
print(row)
finally:
cursor.close()
conn.close()
- โบ ์ฌ์ฉ ์์์ ์คํ ๊ฒฐ๊ณผ
1
select_emp_by_deptno(10)
1 2 3
(1001, 'KIM', 'DEVELOPER', datetime.date(2022, 3, 1), Decimal('3800000.00'), 10) (1002, 'LEE', 'DEVELOPER', datetime.date(2021, 7, 15), Decimal('4200000.00'), 10) (1003, 'PARK', 'MANAGER', datetime.date(2019, 5, 20), Decimal('5500000.00'), 10)
๐ ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ
PyMySQL์์๋ SQL ์์ ๊ฐ์ ์ง์ ์์ฑํ์ง ์๊ณ %s๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ ์ ๋ฌํ๋ค.
%s๋ SQL ์์ ๊ฐ์ ์ง์ ๋ฃ๋ ์๋ฆฌ๊ฐ ์๋๋ผ, PyMySQL์ด ๊ฐ์ ์์ ํ๊ฒ ์ ๋ฌํ๊ธฐ ์ํ ์๋ฆฌ ํ์์(Placeholder)์ด๋ค.
1
2
3
4
5
6
7
8
sql = """
SELECT empno, ename, job, hiredate, sal, deptno
FROM emp
WHERE deptno = %s
ORDER BY empno
"""
cursor.execute(sql, (deptno,))
execute()์ ๋ ๋ฒ์งธ ์ธ์๋ ํํ(tuple) ๋๋ ๋ฆฌ์คํธ(list) ํํ๋ก ์ ๋ฌํด์ผ ํ๋ค.
๊ฐ์ด ํ๋๋ง ์์ด๋ (deptno)๊ฐ ์๋๋ผ (deptno,)์ฒ๋ผ ์ผํ๋ฅผ ๋ถ์ฌ ํํ๋ก ๋ง๋ค์ด์ผ ํ๋ค.
PyMySQL์์๋ ๋ฐ์ดํฐ ํ์
๊ณผ ๊ด๊ณ์์ด ๋ชจ๋ ํ๋ผ๋ฏธํฐ ์๋ฆฌ์ %s๋ฅผ ์ฌ์ฉํ๋ค. ๋ฌธ์์ด๋ฟ ์๋๋ผ ์ซ์, ๋ ์ง ๋ฑ์ ๊ฐ๋ ๋ชจ๋ %s๋ก ์ ๋ฌํ๋ฉฐ, ์ค์ ๋ฐ์ดํฐ ํ์
์ ๋ง๋ ์ฒ๋ฆฌ๋ PyMySQL์ด ์๋์ผ๋ก ์ํํ๋ค.
์ด์ฒ๋ผ SQL๊ณผ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฆฌํ์ฌ ์ ๋ฌํ๋ฉด SQL ๋ฌธ์ด ๋ ์ฝ๊ธฐ ์ฌ์์ง๊ณ , ์ ๋ ฅ๊ฐ์ด SQL ๋ฌธ๋ฒ์ผ๋ก ํด์๋์ง ์์ผ๋ฏ๋ก SQL Injection์ ์๋ฐฉํ ์ ์๋ค.
โจ๏ธ ์์ : ๋จ์ผ ์ฌ์ ์กฐํ
์กฐํ ๊ฒฐ๊ณผ๊ฐ ํ ๊ฑด๋ง ํ์ํ๋ค๋ฉด fetchone()์ ์ฌ์ฉํ ์ ์๋ค.
์กฐ๊ฑด์ ๋ง๋ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด None์ ๋ฐํํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def select_emp_by_empno(empno):
conn = get_connection()
cursor = conn.cursor()
try:
sql = """
SELECT empno, ename, job, hiredate, sal, deptno
FROM emp
WHERE empno = %s
"""
cursor.execute(sql, (empno,))
row = cursor.fetchone()
print(row)
finally:
cursor.close()
conn.close()
- โบ ์ฌ์ฉ ์์์ ์คํ ๊ฒฐ๊ณผ
1
select_emp_by_empno(1001)
1
(1001, 'KIM', 'DEVELOPER', datetime.date(...), Decimal(...), 10)
๐ ์กฐํ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฉ์๋
| ๋ฉ์๋ | ์ค๋ช |
|---|---|
fetchone() |
์กฐํ ๊ฒฐ๊ณผ ์ค ํ ํ๋ง ๊ฐ์ ธ์จ๋ค |
fetchmany(n) |
์กฐํ ๊ฒฐ๊ณผ ์ค n๊ฐ ํ์ ๊ฐ์ ธ์จ๋ค |
fetchall() |
์กฐํ ๊ฒฐ๊ณผ ์ ์ฒด๋ฅผ ๊ฐ์ ธ์จ๋ค |
์ ์ฒด ๋ชฉ๋ก์ ์ถ๋ ฅํ ๋๋ fetchall()์ ์ฌ์ฉํ๊ณ , ์ฌ์๋ฒํธ์ฒ๋ผ ํ๋์ ํ๋ง ์กฐํํ ๋๋ fetchone()์ ์ฌ์ฉํ๋ ๊ฒ์ด ์์ฐ์ค๋ฝ๋ค.
โ CREATE (์ฝ์ )
๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ ๋, SQL์์๋ INSERT ๋ฌธ์ ์ฌ์ฉํ๋ค.
์กฐํ์ ๋ฌ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ์์ ์ด๋ฏ๋ก, SQL ์คํ ํ ๋ฐ๋์ ํธ๋์ญ์ ์ ์ฒ๋ฆฌํด์ผ ํ๋ค.
๐ ๊ธฐ๋ณธ ์์ฑ ํฌ๋งท
PyMySQL์ ์ฌ์ฉํ ์ฝ์ ํจ์๋ ์ผ๋ฐ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ก ์์ฑํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def ํจ์๋ช
():
conn = get_connection()
cursor = conn.cursor()
try:
sql = """
INSERT INTO ํ
์ด๋ธ๋ช
(์ปฌ๋ผ1, ์ปฌ๋ผ2, ...)
VALUES (%s, %s, ...)
"""
cursor.execute(sql, ๊ฐ)
conn.commit()
except Exception:
conn.rollback()
finally:
cursor.close()
conn.close()
โจ๏ธ ์์ : ์ฌ์ ๋ฑ๋ก
์๋ก์ด ์ฌ์ ์ ๋ณด๋ฅผ emp ํ
์ด๋ธ์ ์ถ๊ฐํ๋ ํจ์์ด๋ค.
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
33
def insert_emp(empno, ename, job, hiredate, sal, deptno):
conn = get_connection()
cursor = conn.cursor()
try:
sql = """
INSERT INTO emp (
empno,
ename,
job,
hiredate,
sal,
deptno
)
VALUES (%s, %s, %s, %s, %s, %s)
"""
cursor.execute(
sql,
(empno, ename, job, hiredate, sal, deptno)
)
conn.commit()
print("์ฌ์ ๋ฑ๋ก์ด ์๋ฃ๋์์ต๋๋ค.")
except Exception as e:
conn.rollback()
print(f"์ค๋ฅ ๋ฐ์ : {e}")
finally:
cursor.close()
conn.close()
- โบ ์ฌ์ฉ ์์์ ์คํ ๊ฒฐ๊ณผ
1 2 3 4 5 6 7 8
insert_emp( 1011, "SONG", "DEVELOPER", "2024-01-15", 3900000, 20 )
1
์ฌ์ ๋ฑ๋ก์ด ์๋ฃ๋์์ต๋๋ค.
๐ try-except-finally๋ฅผ ์ฌ์ฉํ๋ ์ด์
๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ์์ ์์๋ ์์ธ ์ฒ๋ฆฌ๊ฐ ํ์์ ์ด๋ค.
1
2
3
4
5
6
7
8
9
10
try:
cursor.execute(sql, values)
conn.commit()
except Exception:
conn.rollback()
finally:
cursor.close()
conn.close()
์ด ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ฉด ์์ธ๊ฐ ๋ฐ์ํ๋๋ผ๋ ๋ฐ์ดํฐ์ ์ผ๊ด์ฑ์ ์ ์งํ๊ณ , ์ฌ์ฉํ ์์์ ์์ ํ๊ฒ ์ ๋ฆฌํ ์ ์๋ค.
โ๏ธ UPDATE (์์ )
๋ฐ์ดํฐ๋ฅผ ์์ ํ ๋, SQL์์๋ UPDATE ๋ฌธ์ ์ฌ์ฉํ๋ค.
๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ์์
์ด๋ฏ๋ก INSERT์ ๋ง์ฐฌ๊ฐ์ง๋ก ํธ๋์ญ์
(commit / rollback) ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค.
๐ ๊ธฐ๋ณธ ์์ฑ ํฌ๋งท
PyMySQL์ ์ฌ์ฉํ ์์ ํจ์๋ ์ผ๋ฐ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ก ์์ฑํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def ํจ์๋ช
():
conn = get_connection()
cursor = conn.cursor()
try:
sql = """
UPDATE ํ
์ด๋ธ๋ช
SET ์ปฌ๋ผ๋ช
= %s
WHERE ์กฐ๊ฑด
"""
cursor.execute(sql, ๊ฐ)
conn.commit()
except Exception:
conn.rollback()
finally:
cursor.close()
conn.close()
โจ๏ธ ์์ : ์ฌ์ ๊ธ์ฌ ์์
์ฌ์๋ฒํธ๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ธ์ฌ๋ฅผ ์์ ํ๋ ํจ์์ด๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def update_emp_sal(empno, sal):
conn = get_connection()
cursor = conn.cursor()
try:
sql = """
UPDATE emp
SET sal = %s
WHERE empno = %s
"""
cursor.execute(sql, (sal, empno))
conn.commit()
print("์ฌ์ ์ ๋ณด๊ฐ ์์ ๋์์ต๋๋ค.")
except Exception as e:
conn.rollback()
print(f"์ค๋ฅ ๋ฐ์ : {e}")
finally:
cursor.close()
conn.close()
- โบ ์ฌ์ฉ ์์์ ์คํ ๊ฒฐ๊ณผ
1
update_emp_sal(1001, 4000000)
1
์ฌ์ ์ ๋ณด๊ฐ ์์ ๋์์ต๋๋ค.
์์ ํ ๋ค์ ์กฐํํ๋ฉด ๋ณ๊ฒฝ๋ ๋ด์ฉ์ ํ์ธํ ์ ์๋ค.
1
select_emp_by_empno(1001)
1
(1001, 'KIM', 'DEVELOPER', datetime.date(2022, 3, 1), Decimal('4000000.00'), 10)
โจ๏ธ ์์ : ์ฌ๋ฌ ์ปฌ๋ผ ์์ ํ๊ธฐ
SET ์ ์๋ ์ฌ๋ฌ ๊ฐ์ ์ปฌ๋ผ์ ์ง์ ํ ์ ์๋ค.
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
def update_emp(empno, job, sal):
conn = get_connection()
cursor = conn.cursor()
try:
sql = """
UPDATE emp
SET
job = %s,
sal = %s
WHERE empno = %s
"""
cursor.execute(sql, (job, sal, empno))
conn.commit()
print("์ฌ์ ์ ๋ณด๊ฐ ์์ ๋์์ต๋๋ค.")
except Exception as e:
conn.rollback()
print(f"์ค๋ฅ ๋ฐ์ : {e}")
finally:
cursor.close()
conn.close()
- โบ ์ฌ์ฉ ์์์ ์คํ ๊ฒฐ๊ณผ
1 2 3 4 5
update_emp( 1007, "SENIOR SALESMAN", 3800000 )
1
์ฌ์ ์ ๋ณด๊ฐ ์์ ๋์์ต๋๋ค.
๋ณ๊ฒฝ ๋ด์ฉ์ ์กฐํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
1
select_emp_by_empno(1007)
1
(1007, 'YOON', 'SENIOR SALESMAN', datetime.date(2021, 12, 20), Decimal('3800000.00'), 30)
๐ execute() : ์คํ๋ ํ(Row)์ ๊ฐ์ ๋ฐํ
execute()๋ SQL ์คํ ํ ์ํฅ์ ๋ฐ์ ํ(row)์ ๊ฐ์๋ฅผ ๋ฐํํ๋ค.
1
2
3
count = cursor.execute(sql, (sal, empno))
print(count)
์คํ ๊ฒฐ๊ณผ
1
1
์กฐ๊ฑด์ ๋ง๋ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ฐํ๋๋ค.
1
0
์ด๋ฅผ ์ด์ฉํ๋ฉด ์์ ์ฑ๊ณต ์ฌ๋ถ๋ฅผ ๊ฐ๋จํ๊ฒ ํ์ธํ ์ ์๋ค.
1
2
3
4
5
6
7
count = cursor.execute(sql, (sal, empno))
if count > 0:
conn.commit()
print("์์ ์๋ฃ")
else:
print("์์ ํ ๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค.")
๐๏ธ DELETE (์ญ์ )
๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ ๋, SQL์์๋ DELETE ๋ฌธ์ ์ฌ์ฉํ๋ค.
๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ์์
์ด๋ฏ๋ก INSERT, UPDATE์ ๋ง์ฐฌ๊ฐ์ง๋ก ํธ๋์ญ์
(commit / rollback) ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค.
๐ ๊ธฐ๋ณธ ์์ฑ ํฌ๋งท
PyMySQL์ ์ฌ์ฉํ ์ญ์ ํจ์๋ ์ผ๋ฐ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ก ์์ฑํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def ํจ์๋ช
():
conn = get_connection()
cursor = conn.cursor()
try:
sql = """
DELETE FROM ํ
์ด๋ธ๋ช
WHERE ์กฐ๊ฑด
"""
cursor.execute(sql, ๊ฐ)
conn.commit()
except Exception:
conn.rollback()
finally:
cursor.close()
conn.close()
โจ๏ธ ์์ : ์ฌ์ ์ญ์
์ฌ์๋ฒํธ๋ฅผ ๊ธฐ์ค์ผ๋ก ์ฌ์ ์ ๋ณด๋ฅผ ์ญ์ ํ๋ ํจ์์ด๋ค.
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
def delete_emp(empno):
conn = get_connection()
cursor = conn.cursor()
try:
sql = """
DELETE FROM emp
WHERE empno = %s
"""
count = cursor.execute(sql, (empno,))
if count > 0:
conn.commit()
print("์ฌ์ ์ ๋ณด๊ฐ ์ญ์ ๋์์ต๋๋ค.")
else:
print("์ญ์ ํ ์ฌ์์ด ์กด์ฌํ์ง ์์ต๋๋ค.")
except Exception as e:
conn.rollback()
print(f"์ค๋ฅ ๋ฐ์ : {e}")
finally:
cursor.close()
conn.close()
- โบ ์ฌ์ฉ ์์์ ์คํ ๊ฒฐ๊ณผ
1
delete_emp(1011)
1
์ฌ์ ์ ๋ณด๊ฐ ์ญ์ ๋์์ต๋๋ค.
์ญ์ ํ ๋ค์ ์กฐํํ๋ฉด ํด๋น ์ฌ์์ด ๋ ์ด์ ์กด์ฌํ์ง ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
1
select_emp_by_empno(1011)
1
None
๐ ์กด์ฌํ์ง ์๋ ๋ฐ์ดํฐ ์ญ์
์กฐ๊ฑด์ ๋ง๋ ๋ฐ์ดํฐ๊ฐ ์๋๋ผ๋ DELETE ๋ฌธ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
๋์ execute()์ ๋ฐํ๊ฐ์ด 0์ด ๋๋ค.
1
delete_emp(9999)
1
์ญ์ ํ ์ฌ์์ด ์กด์ฌํ์ง ์์ต๋๋ค.
๐ execute() ๋ฐํ๊ฐ ํ์ฉ
execute()๋ ์ํฅ์ ๋ฐ์ ํ(Row)์ ๊ฐ์๋ฅผ ๋ฐํํ๋ค.
1
count = cursor.execute(sql, (empno,))
| ๋ฐํ๊ฐ | ์๋ฏธ |
|---|---|
1 |
์ญ์ ์ฑ๊ณต |
0 |
์ญ์ ํ ๋ฐ์ดํฐ ์์ |
์ด๋ฅผ ์ด์ฉํ๋ฉด ์ญ์ ์ฑ๊ณต ์ฌ๋ถ๋ฅผ ์ฝ๊ฒ ํ์ธํ ์ ์๋ค.
1
2
3
4
5
6
count = cursor.execute(sql, (empno,))
if count > 0:
conn.commit()
else:
print("์ญ์ ํ ์ฌ์์ด ์กด์ฌํ์ง ์์ต๋๋ค.")
๐ก์ฐธ๊ณ
DELETE๋ ๋ฐ์ดํฐ๋ฅผ ์ ๊ฑฐํ์ง๋ง ํ ์ด๋ธ ๊ตฌ์กฐ๋ ๊ทธ๋๋ก ์ ์ง๋๋ค. ํ ์ด๋ธ์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋น ๋ฅด๊ฒ ์ญ์ ํ๋ ค๋ฉดTRUNCATE TABLE์ ์ฌ์ฉํ ์๋ ์์ง๋ง,TRUNCATE๋ ๋์ ๋ฐฉ์๊ณผ ํธ๋์ญ์ ์ฒ๋ฆฌ ๋ฐฉ์์ด ๋ค๋ฅด๋ฏ๋ก ์ด๋ฒ ํฌ์คํ ์์๋ ๊ฐ์ฅ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๋DELETE๋ฅผ ๊ธฐ์ค์ผ๋ก ์ค๋ช ํ๋ค.
๐ฅ๏ธ ํตํฉ ํ๋ก๊ทธ๋จ ๊ตฌํ
์ง๊ธ๊น์ง ์์ฑํ CRUD ํจ์๋ค์ ํ๋์ ํ๋ก๊ทธ๋จ์์ ์คํํ ์ ์๋๋ก ํตํฉํ๋ค.
์ด ์ฅ์์๋ ๋จ์ํ ๋ฉ๋ด๋ฅผ ์ถ๋ ฅํ๋ ๊ฒ๋ฟ๋ง ์๋๋ผ, ์ฌ์ฉ์ ์ ๋ ฅ์ ์์ ํ๊ฒ ์ฒ๋ฆฌํ๊ธฐ ์ํ ๋ณด์กฐ ํจ์๋ ํจ๊ป ์์ฑํ๋ค.
โจ๏ธ ๋ณด์กฐ ํจ์
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
from datetime import datetime
# ์
๋ ฅ ์ฒ๋ฆฌ ํจ์
def input_int(message):
while True:
try:
return int(input(message))
except ValueError:
print("์ซ์๋ง ์
๋ ฅํด์ฃผ์ธ์.")
# ๋ ์ง ์
๋ ฅ ์ฒ๋ฆฌ ํจ์
def input_date(message):
while True:
value = input(message)
try:
datetime.strptime(value, "%Y-%m-%d")
return value
except ValueError:
print("๋ ์ง๋ YYYY-MM-DD ํ์์ผ๋ก ์
๋ ฅํด์ฃผ์ธ์.")
# ์ฌ์ ์ ๋ณด ์
๋ ฅ ํจ์
def input_emp_info():
empno = input_int("์ฌ์๋ฒํธ : ")
ename = input("์ฌ์๋ช
: ").upper()
job = input("์ง๊ธ : ").upper()
hiredate = input_date("์
์ฌ์ผ(YYYY-MM-DD) : ")
sal = input_int("๊ธ์ฌ : ")
deptno = input_int("๋ถ์๋ฒํธ : ")
return empno, ename, job, hiredate, sal, deptno
| ํจ์ | ์ญํ |
|---|---|
input_int() |
์ซ์ ์
๋ ฅ์ ๋ฐ์ ์ ์(int)๋ก ๋ณํํ๋ฉฐ, ์๋ชป๋ ์
๋ ฅ์ด ๋ค์ด์ค๋ฉด ๋ค์ ์
๋ ฅ๋ฐ๋๋ค. |
input_date() |
๋ ์ง๋ฅผ ์
๋ ฅ๋ฐ์ YYYY-MM-DD ํ์์ธ์ง ๊ฒ์ฆํ๊ณ , ์ฌ๋ฐ๋ฅธ ํ์์ด ์
๋ ฅ๋ ๋๊น์ง ๋ฐ๋ณตํ๋ค. |
input_emp_info() |
์ฌ์ ๋ฑ๋ก์ ํ์ํ ์ ๋ณด๋ฅผ ํ ๋ฒ์ ์ ๋ ฅ๋ฐ์ ํํ ํํ๋ก ๋ฐํํ๋ค. |
โจ๏ธ ํตํฉ ์คํ ํจ์
์์์ ๋ง๋ ์ ๋ ฅ ์ฒ๋ฆฌ ํจ์์ CRUD ํจ์๋ฅผ ์ฐ๊ฒฐํ๋ค.
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
33
34
def main():
while True:
print("\n===== ์ฌ์ ๊ด๋ฆฌ ์์คํ
=====")
print("1. ์ ์ฒด ์ฌ์ ์กฐํ")
print("2. ์ฌ์ ๋ฑ๋ก")
print("3. ์ฌ์ ๊ธ์ฌ ์์ ")
print("4. ์ฌ์ ์ญ์ ")
print("0. ์ข
๋ฃ")
menu = input("๋ฉ๋ด ์ ํ : ").strip()
if menu == "1":
select_all_emp()
elif menu == "2":
emp_info = input_emp_info()
insert_emp(*emp_info)
elif menu == "3":
empno = input_int("์ฌ์๋ฒํธ : ")
sal = input_int("๋ณ๊ฒฝํ ๊ธ์ฌ : ")
update_emp_sal(empno, sal)
elif menu == "4":
empno = input_int("์ญ์ ํ ์ฌ์๋ฒํธ : ")
delete_emp(empno)
elif menu == "0":
print("ํ๋ก๊ทธ๋จ์ ์ข
๋ฃํฉ๋๋ค.")
break
else:
print("์ฌ๋ฐ๋ฅธ ๋ฉ๋ด๋ฅผ ์ ํํด์ฃผ์ธ์.")
โจ๏ธ ํ๋ก๊ทธ๋จ ์คํ
1
2
if __name__ == "__main__":
main()
๐ก๏ธ SQL Injection ๋ฐฉ์ง
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๋ํ๋ ํ๋ก๊ทธ๋จ์์๋ SQL ๋ฌธ๊ณผ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฆฌํ์ฌ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ๋งค์ฐ ์ค์ํ๋ค.
PyMySQL์์๋ ์ด๋ฅผ ์ํด ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ(Parameter Binding) ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
์ด๋ฒ ์ฅ์์๋ ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ์ด ์ด๋ป๊ฒ ๋์ํ๋ฉฐ, ์ SQL Injection์ ๋ฐฉ์งํ ์ ์๋์ง ์ดํด๋ณธ๋ค.
๐ PyMySQL ๋ด๋ถ ๋์
execute()๋ฅผ ํธ์ถํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์์๋ก ๋์ํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Python ์ฝ๋
โ
โผ
SQL ๋ฌธ
SELECT * FROM emp WHERE empno = %s
โ
โ
์
๋ ฅ๊ฐ
1001
โ
โผ
PyMySQL
โ
(SQL๊ณผ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฆฌํ์ฌ ์ ๋ฌ)
โผ
MySQL Server
โ
โผ
SQL ์คํ
PyMySQL์ SQL๊ณผ ์ ๋ ฅ๊ฐ์ ๋ถ๋ฆฌํ์ฌ ์ฒ๋ฆฌํ๋ค.
์ ๋ ฅ๊ฐ์ PyMySQL์ด ์์ ํ๊ฒ ์ฒ๋ฆฌํ ํ SQL์ด ์คํ๋๋ฏ๋ก, ์ ๋ ฅ๊ฐ์ด SQL ๋ฌธ๋ฒ์ผ๋ก ํด์๋์ง ์์ SQL Injection์ ์๋ฐฉํ ์ ์๋ค.
๐ SQL Injection์ด ๋ฐฉ์ง๋๋ ์ด์
์ฌ์ฉ์๊ฐ ๋ค์๊ณผ ๊ฐ์ ๊ฐ์ ์ ๋ ฅํ๋ค๊ณ ๊ฐ์ ํด ๋ณด์.
1
' OR '1'='1
ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ์ ์ฌ์ฉํ๋ฉด MySQL์ ์ด๊ฒ์
1
"' OR '1'='1"
์ด๋ผ๋ ํ๋์ ๋ฌธ์์ด ๋ฐ์ดํฐ๋ก ์ฒ๋ฆฌํ๋ค.
์ฆ,
1
WHERE ename = "' OR '1'='1"
์ด๋ผ๋ ์๋ฏธ๊ฐ ๋ ๋ฟ, SQL ๋ฌธ์ฅ์ ๊ตฌ์กฐ๋ ์ ํ ๋ณ๊ฒฝ๋์ง ์๋๋ค.
์ด์ฒ๋ผ ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ์ ์ฌ์ฉํ๋ฉด ์ ๋ ฅ๊ฐ์ SQL ๋ฌธ์ฅ์ ์ผ๋ถ๊ฐ ์๋๋ผ ํ๋์ ๋ฐ์ดํฐ๋ก ์ ๋ฌ๋๋ค.
๋ฐ๋ผ์ ์
๋ ฅ๊ฐ์ ์์๋ฐ์ดํ('), OR, -- ๋ฑ์ SQL ๋ฌธ๋ฒ์ ์ฌ์ฉ๋๋ ํน์๋ฌธ์๊ฐ ํฌํจ๋์ด ์๋๋ผ๋ SQL ๋ฌธ๋ฒ์ผ๋ก ํด์๋์ง ์๊ณ ์ผ๋ฐ ๋ฌธ์์ด๋ก ์ฒ๋ฆฌ๋๋ฏ๋ก SQL Injection์ ๋ฐฉ์งํ ์ ์๋ค.
๐ ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ์ ์ถ๊ฐ ์ฅ์
ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ์ ๋ณด์๋ฟ๋ง ์๋๋ผ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ ํธ๋ฆฌํ๊ฒ ๋ง๋ค์ด ์ค๋ค.
| ์ฅ์ | ์ค๋ช |
|---|---|
| SQL๊ณผ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฆฌ | SQL ๊ตฌ์กฐ๊ฐ ๋ณ๊ฒฝ๋์ง ์๋๋ค. |
| SQL Injection ๋ฐฉ์ง | ์ ๋ ฅ๊ฐ์ด SQL ์ฝ๋๋ก ํด์๋์ง ์๋๋ค. |
| ๋ฐ์ดํฐ ํ์ ์๋ ์ฒ๋ฆฌ | ๋ฌธ์์ด, ์ซ์, ๋ ์ง ๋ฑ์ ์ ์ ํ ํํ๋ก ๋ณํํ๋ค. |
| ์ฝ๋ ๊ฐ๋ ์ฑ ํฅ์ | SQL๊ณผ ๋ฐ์ดํฐ๊ฐ ๋ช ํํ๊ฒ ๊ตฌ๋ถ๋๋ค. |
๐ ์ ๋ฆฌ
PyMySQL ์ฃผ์ ๊ฐ์ฒด
| ๊ฐ์ฒด | ์ญํ |
|---|---|
Connection |
MySQL ์๋ฒ์ ์ฐ๊ฒฐ์ ๊ด๋ฆฌ |
Cursor |
SQL์ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ |
์์ฃผ ์ฌ์ฉํ๋ PyMySQL์ ๋ฉ์๋
| ๋ฉ์๋ | ์ค๋ช |
|---|---|
cursor.execute() |
SQL์ ์คํ |
cursor.fetchone() |
๊ฒฐ๊ณผ 1๊ฑด์ ๋ฐํ |
cursor.fetchmany(n) |
๊ฒฐ๊ณผ n๊ฑด์ ๋ฐํ |
cursor.fetchall() |
์ ์ฒด ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ |
conn.commit() |
๋ณ๊ฒฝ ๋ด์ฉ์ ์ ์ฅ |
conn.rollback() |
๋ณ๊ฒฝ ๋ด์ฉ์ ์ทจ์ |
cursor.close() |
Cursor๋ฅผ ์ข ๋ฃ |
conn.close() |
Connection์ ์ข ๋ฃ |
ํธ๋์ญ์
SELECT๋commit()์ด ํ์ํ์ง ์์INSERT,UPDATE,DELETE๋commit()์ด ํ์- ์ค๋ฅ ๋ฐ์ ์
rollback()์ํ
ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ
- SQL๊ณผ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฆฌํ์ฌ ์ ๋ฌ
- SQL Injection ๋ฐฉ์ง
- ๊ฐ์ด ํ๋์ฌ๋
(value,)ํํ์ ํํ ์ฌ์ฉ
CRUD ๊ธฐ๋ณธ ํ๋ฆ
- READ :
execute()โfetch()โclose() - CREATE / UPDATE / DELETE :
execute()โcommit()โclose()
PyMySQL ์์ ์์
1
2
3
4
5
6
7
8
9
10
11
12
Connection ์์ฑ
โ
Cursor ์์ฑ
โ
SQL ์์ฑ ๋ฐ execute()
โ
READ โ fetch()
CUD โ commit()
โ
Cursor ์ข
๋ฃ
โ
Connection ์ข
๋ฃ