[DB] SQLModel로 데이터베이스 다루기 <2>
공식문서 참조
1. INSERT INTO…
테이블을 만들었으니 데이터를 넣어보자. 순서는 다음과 같다.
- Engine을 통해 Session을 만든다.
- Session을 통해 쿼리를 작성한다.
- commit
- Session 종료
1.1 Session 반환 함수
1
2
3
4
5
6
7
async def get_async_session():
async_session = async_sessionmaker(
bind=async_engine,
class_=AsyncSession,
)
async with async_session() as session:
yield session
비동기적으로 만들었기 때문에 yield
로 반환한다.
1.2 엔드포인트에서 Depends로 활용
1
2
3
4
5
6
7
8
9
10
@app.post("/", status_code=status.HTTP_201_CREATED)
async def create_heros(session:Annotated[AsyncSession, Depends(get_async_session)]):
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
async with session.begin():
session.add_all([hero_1, hero_2, hero_3])
return {"msg": "Heros created"}
해당 엔드포인트에 post 요청이 들어오면 미리 만들어둔 히어로를 db에 추가한다.
Depens
를 활용하면 의존성 주입을 통해 간단하게 구현 가능하다.
자동 커밋, 롤백을 위해 session.begin()
으로 추가한다.
1.3 결과
만들어준 히어로들이 추가됐다.
2. SELECT
위에서 입력한 데이터들을 조회해보자.
1
2
3
4
5
6
7
8
9
10
from sqlmodel import select
@app.get("/", status_code=status.HTTP_200_OK)
async def get_heros(session:Annotated[AsyncSession, Depends(get_async_session)]):
async with session.begin():
statement = select(Hero)
results = await session.exec(statement)
heros = results.all()
return heros
sqlmodel
의 select
를 사용해 SQL 문법의 SELECT
를 구현할 수 있다.
SQLModel
을 상속한 클래스를 select에 매개변수로 넘겨주면 테이블의 모든 컬럼을 불러오게 된다.
이때 execute 한 결과물에 .all()
메서드를 사용하면 모든 객체를 리스트로 불러올 수 있다. 종류는 아래와 같다.
.all()
: 모든 행을 리스트로 반환.first()
: 결과의 첫 번째 행만 반환.one()
: 결과 중 단 하나의 행만 반환. 하나의 행보다 많으면 오류 발생.one_or_none()
: 하나의 행 또는 None을 반환. 여러 행이면 오류.fetchmany(size)
: 지정한 사이즈의 갯수만큼 반환함..partitions(size)
: 지정한 size 만큼의 쿼리 결과를 그룹으로 나누어 처리.
.fetchall()
로 조회한 결과물들이다. 잘 조회된다.
3. WHERE
SQL 문에서 WHERE
은 특정 조건의 데이터만 검색하기 위한 쿼리다.
1
2
3
4
5
6
7
8
9
10
11
@app.get("/{word}", status_code=status.HTTP_200_OK)
async def get_heros(
session:Annotated[AsyncSession, Depends(get_async_session)],
word: str
):
async with session.begin():
statement = select(Hero).where(Hero.name == word)
results = await session.exec(statement)
heros = results.fetchall()
return heros
위의 api를 살짝 변형해 url에서 특정 word를 검색어로 활용해 get 메서드를 사용하게 만들었다.
이때 word
와 테이블의 객체의 name
이 같은 행만 반환하게 된다.
잘 반환된다.
3.1 SELECT
vs WHERE
이 두 가지 sql 문을 사용할 때는 다음과 같은 팁이 있다.
SELECT
는 데이터베이스에서 특정 열을 리턴하기 위해 사용한다.1
statement = select(Hero.name) ... # 히어로들의 이름을 리턴함.
WEHRE
은 데이터베이스에서 특정 행을 리턴하기 위해 사용한다.1
statement = select(Hero).where(Hero.name == "Deadpond") # 특정 이름을 가진 히어로 정보를 리턴함.
3.2 조건문
==
뿐만이 아니라 부등호, 부정문을 사용한 조건문도 가능하다.
≠
1
statement = select(Hero).where(Hero.name != "Deadpond") # 특정 히어로의 이름이 아닌 경우를 리턴함
부등호
1
statement = select(Hero).where(Hero.age > 35) # 35세 초과의 히어로만 리턴함.
3.3 중복 WHERE
where
을 중복으로 사용하는것도 가능하다.
1
statement = select(Hero).where(Hero.age >= 35).where(Hero.age < 40) # 35세 이상, 40세 미만의 히어로를 리턴함
다른 표현
1
statement = select(Hero).where(Hero.age >= 35, Hero.age < 40)
3.4 _or
_or
을 임포트하면 or 조건도 사용 가능하다.
1
2
3
4
from sqlmodel import Field, Session, SQLModel, create_engine, or_, select
statement = select(Hero).where(or_(Hero.age <= 35, Hero.age > 90))
# 35세 이하, 혹은 90세 초과 히어로를 리턴한다.