one()과 first()의 차이점
반환 값:
one()
: 쿼리 결과가 정확히 하나인 경우 해당 레코드를 반환합니다. 쿼리 결과가 없거나 둘 이상인 경우 예외를 발생시킵니다.first()
: 쿼리 결과가 하나 이상인 경우 첫 번째 레코드를 반환합니다. 쿼리 결과가 없는 경우None
을 반환합니다.
예외 처리:
one()
: 쿼리 결과가 하나 이상인 경우 예외를 발생시키므로 코드에서 명시적으로 처리해야 합니다.first()
: 쿼리 결과가 하나 이상인 경우 예외를 발생시키지 않으므로 코드에서 별도의 예외 처리가 필요하지 않습니다.
성능:
one()
: 쿼리 결과가 하나 이상인 경우 모든 레코드를 읽어야 하기 때문에first()
보다 성능이 저하될 수 있습니다.first()
: 쿼리 결과의 첫 번째 레코드만 읽어오기 때문에one()
보다 성능이 좋습니다.
사용 시나리오:
one()
: 쿼리 결과가 정확히 하나임을 확신하는 경우 사용합니다. 예를 들어, 주어진 ID에 해당하는 사용자 정보를 가져오는 경우 사용할 수 있습니다.first()
: 쿼리 결과가 하나 이상일 수 있는 경우 사용합니다. 예를 들어, 최신 게시글 목록을 가져오는 경우 사용할 수 있습니다.
요약:
메서드 | 반환 값 | 예외 처리 | 성능 | 사용 시나리오 |
---|---|---|---|---|
one() | 정확히 하나의 레코드 | 예외 발생 | 낮음 | 쿼리 결과가 하나임을 확신하는 경우 |
first() | 첫 번째 레코드 또는 None | 예외 발생하지 않음 | 높음 | 쿼리 결과가 하나 이상일 수 있는 경우 |
참고:
one_or_none()
메서드는one()
과 유사하지만 쿼리 결과가 없는 경우None
을 반환합니다.limit(1)
메서드는 쿼리 결과를 1개만 제한하지만one()
이나first()
만큼 직관적이지 않습니다.
예시:
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
engine = create_engine('sqlite:///mydb.db')
Base.metadata.create_all(engine)
session = sessionmaker(bind=engine)()
# 쿼리 결과가 정확히 하나인 경우
user = session.query(User).filter(User.name == 'John').one()
# 쿼리 결과가 하나 이상일 수 있는 경우
users = session.query(User).filter(User.name.like('%John%')).first()
예제 코드
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
engine = create_engine('sqlite:///mydb.db')
Base.metadata.create_all(engine)
session = sessionmaker(bind=engine)()
# 1. `one()` 메서드 예시
try:
# 쿼리 결과가 정확히 하나인 경우
user = session.query(User).filter(User.name == 'John').one()
print(f"사용자 정보: {user.name}")
except sqlalchemy.orm.NoResultFound:
print("존재하지 않는 사용자입니다.")
except sqlalchemy.orm.MultipleResultsFound:
print("동일한 이름의 사용자가 여러 명 존재합니다.")
# 2. `first()` 메서드 예시
users = session.query(User).filter(User.name.like('%John%')).first()
if users:
print(f"첫 번째 사용자 정보: {users.name}")
else:
print("John으로 시작하는 이름의 사용자가 없습니다.")
-
one()
메서드 예시:User
테이블에서name
이 'John'인 사용자 정보를 가져옵니다.- 쿼리 결과가 정확히 하나인 경우 사용자 정보를 출력합니다.
- 쿼리 결과가 없거나 둘 이상인 경우 예외를 발생시키고 적절한 메시지를 출력합니다.
-
first()
메서드 예시:- 쿼리 결과가 없는 경우 'John'으로 시작하는 이름의 사용자가 없음을 출력합니다.
one()
과 first()
메서드의 대체 방법
fetchone() 메서드:
fetchone()
메서드는 cursor
객체에서 첫 번째 레코드를 가져오는 데 사용됩니다. 다음과 같이 사용할 수 있습니다.
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
engine = create_engine('sqlite:///mydb.db')
Base.metadata.create_all(engine)
session = sessionmaker(bind=engine)()
# 쿼리 결과가 정확히 하나인 경우
cursor = session.query(User).filter(User.name == 'John').cursor()
user = cursor.fetchone()
if user:
print(f"사용자 정보: {user.name}")
else:
print("존재하지 않는 사용자입니다.")
LIMIT 1:
LIMIT 1
키워드를 사용하여 쿼리 결과를 1개만 제한할 수 있습니다. 다음과 같이 사용할 수 있습니다.
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
engine = create_engine('sqlite:///mydb.db')
Base.metadata.create_all(engine)
session = sessionmaker(bind=engine)()
# 쿼리 결과가 하나 이상일 수 있는 경우
users = session.query(User).filter(User.name.like('%John%')).limit(1).all()
if users:
print(f"첫 번째 사용자 정보: {users[0].name}")
else:
print("John으로 시작하는 이름의 사용자가 없습니다.")
[0]:
쿼리 결과를 리스트로 받은 후 [0]
인덱스를 사용하여 첫 번째 레코드를 가져올 수 있습니다. 다음과 같이 사용할 수 있습니다.
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
engine = create_engine('sqlite:///mydb.db')
Base.metadata.create_all(engine)
session = sessionmaker(bind=engine)()
# 쿼리 결과가 하나 이상일 수 있는 경우
users = session.query(User).filter(User.name.like('%John%')).all()
if users:
print(f"첫 번째 사용자 정보: {users[0].name}")
else:
print("John으로 시작하는 이름의 사용자가 없습니다.")
주의 사항:
fetchone()
메서드는cursor
객체를 사용해야 하기 때문에 코드가 더 복잡해집니다.LIMIT 1
키워드는 쿼리 성능을 향상시킬 수 있지만, 쿼리 결과가 없는 경우None
을 반환합니다.[0]
인덱스를 사용하는 방법은 가장 간단하지만, 쿼리 결과가 없는 경우 예외를 발생시킵니다.
python sqlalchemy flask-sqlalchemy