Scalar 메서드는 쿼리를 통해 가져온 결과를, 단일 데이터 요소(ex. ORM)로 반환하는 데 사용하는 sqlalchemy.engine.Result 클래스의 메서드입니다. 이번 글에서는 SQLAlchemy에서 제공하는 Scalar 메서드들에 대해 알아보고, 각 메서드들의 적합한 예시를 함께 살펴보겠습니다. 🥸
scalar()
scalar() 메서드는 쿼리 결과의 첫 번째 행의 값을 반환합니다. 만약 결과가 없으면 None을 반환합니다. scalar() 메서드는 주로 결과가 최대 하나만 있을 것으로 예상되거나, 여러 결과 중 첫 번째 값만 필요한 경우에 사용됩니다.
예시: 특정 조건을 만족하는 첫 번째 사용자의 이름 조회
first_user_name = session.query(User.name).filter(User.age > 20).scalar()
if first_user_name:
print(f"조건을 만족하는 첫 번째 사용자의 이름은 {first_user_name}입니다.")
else:
print("조건을 만족하는 사용자가 없습니다.")
이 예시에서는 20세 이상인 사용자 중 첫 번째 사용자 이름을 조회합니다. 결과가 여러 개 있더라도, scalar() 메서드는 첫 번째 사용자의 이름만 반환합니다. 만약 해당 조건을 만족하는 사용자가 없다면, None을 반환하게 되죠.
위 예시 처럼 scalar() 메서드는 결과가 하나 또는 없을 때 유용하게 사용됩니다. 결과가 여러 개 있을 경우에도 첫 번째 결과만을 반환하기 때문에, 결과가 정확히 하나여야 하는 상황에서는 scalar_one() 또는 scalar_one_or_none() 메서드가 더 적합합니다.
scalar_one()
scalar_one() 메서드는 쿼리 결과가 정확히 하나일 때 그 값을 반환합니다. 결과가 없거나, 하나 이상이라면 예외를 발생시킵니다.
예시: 유니크한 사용자 ID로 사용자의 이름을 조회
name = session.query(User.name).filter(User.id == user_id).scalar_one()
print(f"사용자의 이름은 {name}입니다.")
만약 결과가 값을 반환하지 않으면 NoResultFound 예외를, 여러 값을 반환하면 MultipleResultsFound 예외를 발생시킵니다.
scalar_one_or_none()
scalar_one_or_none() 메서드는 결과가 정확히 하나이거나 없을 때 사용합니다. 결과가 하나일 때는 그 값을 반환하고, 없으면 None 을 반환합니다. 만약 결과가 하나 이상이라면 예외를 발생시킵니다.
예시: 유니크한 상품 ID로 상품의 가격을 조회
product_price = session.query(Product.price).filter(Product.id == product_id).scalar_one_or_none()
if product_price is not None:
print(f"제품 가격은 {product_price}원입니다.")
else:
print("해당 제품이 존재하지 않습니다.")
만약 결과가 여러 값을 반환하면 MultipleResultsFound 에외를 발생시킵니다.
scalars()
scalars() 메서드는 쿼리 결과의 값들을 반환합니다. 이 메서드는 ScalarResult 객체를 반환하는데, 해당 객체를 순회하거나 all() 과 같은 메서드를 다시 호출해야 값을 가져올 수 있습니다.
예시: 특정 조건을 만족하는 여러 사용자의 ID를 조회
user_ids = session.query(User.id).filter(User.is_active == True).scalars().all()
print(f"활성 사용자 ID 리스트: {user_ids}") # 활성 사용자 ID 리스트: [1, 3]
scalars() 를 통해 반환된 ScalarResult 객체는 unique(), partitions(), fetchmany() 등의 메서드를 호출하여 원하는 값들만 가져올 수도 있습니다.
scalars().unique() 는 중복되는 객체들을 제거하여 고유한 객체들만 반환합니다. 보통 join 과정에서 중복되는 row 가 생성되면 이 unique() 를 통해 해결할 수 있습니다. The unique() method must be ... 에러 해결방법
result = session.execute(stmt).scalars().unique()
scalars().partitions(size) 는 size 크기 만큼의 순회하는 서브리스트를 반환합니다.
for partition in session.execute(stmt).scalars().partitions(size=10):
for obj in partition:
print(obj)
scalars().fetchall() 은 모든 값을 반환합니다.
results = session.execute(stmt).scalars().fetchall()
scalars().fetchmany(size=10) 는 지정된 수 만큼의 값을 반환합니다.
results = session.execute(stmt).scalars().fetchmany(size=10)
scalars().all() 은 fetchall() 와 동일하게 모든 값을 리스트로 반환합니다.
results = session.execute(stmt).scalars().all()
scalars().first() 는 첫 번째 값을 반환합니다. 만약 값이 없다면 None 을 반환합니다.
result = session.execute(stmt).scalars().first()
scalars().one_or_none() 은 하나의 값을 반환합니다. 만약 값이 많다면 예외를 발생시킵니다.
result = session.execute(stmt).scalars().one_or_none()
scalars().one() 은 하나의 값을 반환합니다. 만약 값이 없거나 많다면 예외를 발생시킵니다.
result = session.execute(stmt).scalars().one()
마무리
'Scalar'는 라틴어 'scala'에서 유래했으며, 이는 '계단'이나 '저울'을 의미합니다. 수학과 물리학에서 '스칼라'는 크기만을 가지고 방향성이 없는 물리량을 뜻하는데요. 프로그래밍에서는 이 개념이 확장되어 단일 값을 나타내는 변수나 데이터를 의미한다고 합니다.
개발 과정에서 DB 데이터를 가져올 때 Scalar 메서드를 자주 사용하는데요. 종종 헷갈릴 때가 있어 이번에 간단히 정리해 보았습니다. 정리하는 과정에서 단어의 뜻과 어원도 배울 수 있었네요. 😚
레퍼런스
'나는 이렇게 학습한다 > DB' 카테고리의 다른 글
Supabase의 RPC를 활용해 실시간 카운터 기능 구현하기 (1) | 2024.09.14 |
---|---|
Sqlalchemy 에서 joinedload 할 때, The unique() method must be ... 에러 해결방법 (0) | 2023.08.30 |
SQLAlchemy _ ForeignKey 로 연결된 개체 한 번에 삭제하기 (0) | 2023.03.24 |
데이터베이스에서 인덱스는 왜 사용하는 걸까? (0) | 2022.03.19 |
트랜젝션이란? (0) | 2022.03.18 |