Post

Python MySQL ์—ฐ๋™ (PyMySQL CRUD)

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 ์ข…๋ฃŒ
This post is licensed under CC BY 4.0 by the author.