[Python] SQLAlchemy

SQLAlchemy๋Š” ํŒŒ์ด์ฌ ํ™˜๊ฒฝ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ORM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‹ค.

๊ธฐ๋ณธ์ ์ธ ๊ตฌ์„ฑ ๋ฐฉ๋ฒ•๊ณผ CRUD ์˜๋Š” ๋ฐฉ๋ฒ• ์ •๋„๋งŒ ์ •๋ฆฌํ•ด๋ณด๊ฒ ๋‹ค.




์„ค์น˜ํ•˜๊ธฐ

์•Œ์ผ€๋ฏธ๋ฅผ ์“ฐ๋ ค๋ฉด ๋ชจ๋“ˆ 2๊ฐœ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
๊น”์•„์ค€๋‹ค.

pip install sqlalchemy psycopg2


๋์œผ๋ฉด ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ๋ฅผ ์žก์•„๋ณด์ž.
๋‚˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์•Œ์ผ€๋ฏธ ๊ด€๋ฆฌ์šฉ ์„œ๋ธŒ๋ชจ๋“ˆ "models"๋ฅผ ๋‘๊ณ , ๊ณตํ†ต์ ์ธ ๊ธฐ๋Šฅ์„ base์— ๋‘๊ณ  ํ…Œ์ด๋ธ”๋ณ„๋กœ ๋ณ„๋„์˜ ์†Œ์ŠคํŒŒ์ผ์„ ๋‘๋Š” ํ˜•ํƒœ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.




๊ธฐ๋ณธ ์—ฐ๊ฒฐ ์„ค์ •

base.py๋ฅผ ๋จผ์ € ๋ณด๊ฒ ๋‹ค.
์—ฌ๊ธฐ์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด๋‚˜, ๊ทธ์™€ ๊ด€๋ จ๋œ ๊ธฐ๋ณธ์ ์ธ ์š”์†Œ๋“ค์„ ๋‹ค ๋„ฃ์–ด๋†จ๋‹ค.

from sqlalchemy.orm import declarative_base

from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import sessionmaker, scoped_session

engine = create_engine("postgresql://postgres:ํŒจ์Šค์›Œ๋“œ@localhost:5432/alchemy_test", echo=True)
get_db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))

Base = declarative_base()

def sync_db():
    Base.metadata.create_all(bind=engine)

get_db_session๋Š” session์„ ๊ฐ€์ ธ์™€์ฃผ๋Š” ํ•จ์ˆ˜์ธ๋ฐ, DB ์ปค๋„ฅ์…˜ ๊ฐœ๋…์ด๋ผ ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.
Base๋Š” ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ •์˜ํ• ๋•Œ ์‚ฌ์šฉํ•  ๊ธฐ๋ฐ˜ ํด๋ž˜์Šค๋‹ค. ์ด๊ฑธ ์ƒ์†๋ฐ›๋Š” ๊ฒƒ์œผ๋กœ ์ดํ›„์— ์ •์˜ํ•  ๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ๊ฐ€ ํ•˜๋‚˜๋กœ ์ œ์–ด๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํ…Œ์ด๋ธ” ์ดˆ๊ธฐํ™”์šฉ ํ•จ์ˆ˜ sync_db๋„ ํ•˜๋‚˜ ์ •์˜ํ•ด๋’€๋‹ค. ์ •์˜ํ•œ ์—”ํ‹ฐํ‹ฐ๋ฅผ create tableํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
์—ฌ๊ธฐ์„œ ๋ฐ”๋กœ ํ•˜์ง€ ์•Š๊ณ  ํ•จ์ˆ˜๋กœ๋งŒ ๋‘” ๊ฒƒ์€, ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์ „๋ถ€ import๋ฅผ ํ†ตํ•ด์„œ load๋œ ์‹œ์ ์—๋งŒ ์œ ํšจํ•˜๊ฒŒ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ €๊ฑด ์ตœ์ƒ์œ„ ๋ชจ๋“ˆ์—์„œ ์‹คํ–‰ํ•˜๊ฒ ๋‹ค.




์—”ํ‹ฐํ‹ฐ ์ •์˜

ํ…Œ์ด๋ธ”์€ ์ด๋Ÿฐ์‹์œผ๋กœ ์ •์˜ํ•˜๋ฉด ๋œ๋‹ค.
Base๋ฅผ ์ƒ์†๋ฐ›๊ณ , __tablename__์œผ๋กœ ํ…Œ์ด๋ธ”๋ช…์„ ์ •์˜ํ•œ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๊ฐ๊ฐ์˜ ์ปฌ๋Ÿผ๋“ค์„ ํ•„๋“œ๋กœ ์ •์˜ํ•ด์„œ Column ๊ฐ์ฒด๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

from sqlalchemy import String, Integer, Column
from .base import Base

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True)
    name = Column(String(30), nullable=True)
    age = Column(Integer, nullable=False, default=0)




ํ…Œ์ด๋ธ” ๋™๊ธฐํ™”ํ•˜๊ธฐ

์—”ํ‹ฐํ‹ฐ๋ฅผ ์ •์˜ํ—€์œผ๋‹ˆ, ๊ทธ๊ฒŒ ์‹ค์ œ ํ…Œ์ด๋ธ”๋กœ ์ƒ๊ฒจ๋‚˜๋„๋ก ๋™๊ธฐํ™”๋ฅผ ํ•ด๋ณด์ž.
importํ•ด์˜จ ์ƒํƒœ์—์„œ sync_db๋ฅผ ํ•ด์ฃผ๋ฉด

์ฃผ๋ฅด๋ฅต ๋œจ๋ฉด์„œ


์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ค€๋‹ค.




๋ฐ์ดํ„ฐ ์‚ฝ์ž…ํ•˜๊ธฐ (add, add_all)

์ด์ œ๋Š” ๋งŒ๋“ค์–ด๋†จ๋˜๊ฑธ ๊ธฐ๋ฐ˜์œผ๋กœ CRUD ์ž‘์—…์„ ํ•˜๋‚˜์”ฉ ํ•ด๋ณด๊ฒ ๋‹ค.

์„ธ์…˜์„ ๊ฐ€์ ธ์™€์„œ ์ด๋ž˜์ €๋ž˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , add๋กœ ์ถ”๊ฐ€ํ•˜๊ณ , ์ปค๋ฐ‹์น˜๊ณ , ์„ธ์…˜์„ ๋‹ซ์œผ๋ฉด ๋œ๋‹ค.

from models import user, base

def main(): 
    db_session = base.get_db_session()

    new_user = user.User(name="John Doe", age=555)

    db_session.add(new_user)
    db_session.commit()

    db_session.close()

main()

์ปค๋ฐ‹์„ ์ณ์•ผ๋จ„ ์ง„์งœ ์ปค๋ฐ‹์ด ๋“ค์–ด๊ฐ„๋‹ค๋Š” ์  ์žŠ์ง€ ๋ง์ž.
์„ธ์…˜๋„ ๊ผญ ๋‹ซ์•„์ฃผ์ž.

์•„๋ฌดํŠผ ์ €๋ ‡๊ฒŒ ์‹คํ–‰ํ•˜๋ฉด

๊ธฐ๋Œ€ํ•œ๋Œ€๋กœ ๋“ค์–ด๊ฐˆ ๊ฒƒ์ด๋‹ค.

๋ฐฐ์—ด๋กœ ๋งŒ๋“ค์–ด์„œ add_all์„ ํ•˜๋ฉด ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ํ•œ๋ฒˆ์— ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค.

from models import user, base

def main(): 
    db_session = base.get_db_session()

    users = [
        user.User(name="John Doe", age=555), 
        user.User(name="Phone Doe", age=666), 
        user.User(name="Alexander", age=444), 
        user.User(name="Jane Doe", age=10)
    ]

    db_session.add_all(users)
    db_session.commit()

    db_session.close()

main()

์ž˜ ๋“ค์–ด๊ฐ”๋‹ค.




๋ฐ์ดํ„ฐ ์กฐํšŒํ•˜๊ธฐ

์กฐํšŒ๋ฅผ ํ• ๋•Œ๋Š” ์ฃผ๋กœ query ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

์•„๋ž˜๋Š” id๊ฐ€ 1์ธ ๊ฐ์ฒด๋งŒ ํ•˜๋‚˜ ์ฐพ์•„์˜ค๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋‹ค.

from models import user, base
from sqlalchemy.engine.row import Row

def main(): 
    db_session = base.get_db_session()

    result = db_session.query(user.User).filter_by(id = 1).first()
    print(result.id, result.name, result.age)

    db_session.close()

main()

์—ฌ๊ธฐ์„œ ์œ ์˜ํ•  ์ ์€, query๋‚˜ filter_by ๊ฐ™์€๊ฑด ๊ทธ๋ƒฅ ์ฟผ๋ฆฌ ํ…์ŠคํŠธ๋งŒ ๋งŒ๋“ค์–ด์ฃผ๋Š” ์—ญํ• ์ด๋ž€ ๊ฒƒ์ด๋‹ค.
์ €๋Ÿฐ ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹์„ ํ†ตํ•ด์„œ ์ƒ์„ฑํ•œ ์ฟผ๋ฆฌ ๊ฐ์ฒด๋ฅผ, first๋‚˜ all ๋“ฑ์˜ ํ•จ์ˆ˜๋กœ ์‹คํ–‰์‹œํ‚ค๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„์˜จ๋‹ค.

all์„ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ๋ฆฌ์ŠคํŠธ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
์•„๋ž˜ ์ฝ”๋“œ๋Š” age๊ฐ€ 555, 666, 777์ธ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋ถ€ selectํ•ด์˜ค๋Š” ์ฝ”๋“œ๋‹ค.

from models import user, base
from sqlalchemy.engine.row import Row

def main(): 
    db_session = base.get_db_session()

    result = db_session.query(user.User) \
        .where(user.User.age.in_([555, 666, 777])) \
        .all()

    for e in result: 
        print(e.id, e.name, e.age)

    db_session.close()

main()

์ž˜ ๊ฐ€์ ธ์˜จ๋‹ค.




๋ฐ์ดํ„ฐ ์ˆ˜์ •ํ•˜๊ธฐ (update)

๋ฐ์ดํ„ฐ์— update๋ฅผ ์น˜๋Š”๊ฒƒ์—๋Š” ํฌ๊ฒŒ 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

์ •์งํ•˜๊ฒŒ update ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๊ณ 

from models import user, base
from sqlalchemy.engine.row import Row

def main(): 
    db_session = base.get_db_session()

    result = db_session.query(user.User) \
        .where(user.User.id.__eq__(1)) \
        .update({"name": "FooBar"})

    db_session.commit()

    db_session.close()

main()

select๋กœ ๊ฐ€์ ธ์˜จ ๊ฐ’์—์„œ ํ•„๋“œ๋งŒ ์กฐ์ž‘ํ•ด์„œ ์–ผ๋ ๋šฑ๋•… ์ˆ˜์ •๋˜๊ฒŒ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

from models import user, base
from sqlalchemy.engine.row import Row

def main(): 
    db_session = base.get_db_session()

    found = db_session.query(user.User) \
        .where(user.User.id.__eq__(3)) \
        .first()

    found.name = "asdf" // ๊ฐ’ ๋ณ€๊ฒฝ!

    db_session.commit() // DB์— ๋ฐ˜์˜!

    db_session.close()

main()




๋ฐ์ดํ„ฐ ์‚ญ์ œํ•˜๊ธฐ (delete)

์ด๋ฒˆ์—๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜ ์ง€์›Œ๋ณด์ž.
update ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ๊ณผ ๋ณ„๋ฐ˜ ๋‹ค๋ฅผ ๊ฒƒ์€ ์—†๋‹ค.

from models import user, base
from sqlalchemy.engine.row import Row

def main(): 
    db_session = base.get_db_session()

    result = db_session.query(user.User) \
        .where(user.User.id.__eq__(2)) \
        .delete()

    db_session.commit()

    db_session.close()

main()

ํ•ด์„œ ์‹คํ–‰์‹œํ‚ค๋ฉด

์ž˜ ์‚ฌ๋ผ์ง„๋‹ค.



์ฐธ์กฐ
https://www.sqlalchemy.org/
https://blog.neonkid.xyz/253