Consultas en SQLAlchemy ORM#
Ultima modificación: Mar 6, 2024 | YouTube
Preparación#
[1]:
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.orm import declarative_base, relationship
Base = declarative_base()
class User(Base):
__tablename__ = "user_account"
id = Column(Integer, primary_key=True)
name = Column(String(30))
fullname = Column(String)
addresses = relationship(
"Address", back_populates="user", cascade="all, delete-orphan"
)
def __repr__(self):
return f"User(id={self.id!r}, name={self.name!r}, fullname={self.fullname!r})"
class Address(Base):
__tablename__ = "address"
id = Column(Integer, primary_key=True)
email_address = Column(String, nullable=False)
user_id = Column(Integer, ForeignKey("user_account.id"), nullable=False)
user = relationship("User", back_populates="addresses")
def __repr__(self):
return f"Address(id={self.id!r}, email_address={self.email_address!r})"
[2]:
from sqlalchemy import create_engine
engine = create_engine(
"sqlite+pysqlite:///:memory:",
echo=False,
future=True,
)
[3]:
Base.metadata.create_all(engine)
[4]:
from sqlalchemy.orm import Session
with Session(engine) as session:
spongebob = User(
name="spongebob",
fullname="Spongebob Squarepants",
addresses=[Address(email_address="spongebob@sqlalchemy.org")],
)
sandy = User(
name="sandy",
fullname="Sandy Cheeks",
addresses=[
Address(email_address="sandy@sqlalchemy.org"),
Address(email_address="sandy@squirrelpower.org"),
],
)
patrick = User(
name="patrick",
fullname="Patrick Star",
)
session.add_all(
[
spongebob,
sandy,
patrick,
]
)
session.commit()
Selección#
[5]:
from sqlalchemy import select
print(select(User))
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
[6]:
row = session.execute(select(User)).first()
row
[6]:
(User(id=1, name='spongebob', fullname='Spongebob Squarepants'),)
[7]:
row[0]
[7]:
User(id=1, name='spongebob', fullname='Spongebob Squarepants')
[8]:
user = session.scalars(select(User)).first()
user
[8]:
User(id=1, name='spongebob', fullname='Spongebob Squarepants')
[9]:
print(select(User.name, User.fullname))
SELECT user_account.name, user_account.fullname
FROM user_account
[10]:
row = session.execute(select(User.name, User.fullname)).first()
row
[10]:
('spongebob', 'Spongebob Squarepants')
[11]:
session.execute(
select(User.name, Address).where(User.id == Address.user_id).order_by(Address.id)
).all()
[11]:
[('spongebob', Address(id=1, email_address='spongebob@sqlalchemy.org')),
('sandy', Address(id=2, email_address='sandy@sqlalchemy.org')),
('sandy', Address(id=3, email_address='sandy@squirrelpower.org'))]
WHERE#
[12]:
from sqlalchemy import and_, or_
print(
select(Address.email_address).where(
and_(
or_(User.name == "squidward", User.name == "sandy"),
Address.user_id == User.id,
)
)
)
SELECT address.email_address
FROM address, user_account
WHERE (user_account.name = :name_1 OR user_account.name = :name_2) AND address.user_id = user_account.id
[13]:
print(select(User).filter_by(name="spongebob", fullname="Spongebob Squarepants"))
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
WHERE user_account.name = :name_1 AND user_account.fullname = :fullname_1
[14]:
from sqlalchemy import func
with engine.connect() as conn:
result = conn.execute(
select(User.name, func.count(Address.id).label("count"))
.join(Address)
.group_by(User.name)
.having(func.count(Address.id) > 1)
)
print(result.all())
[('sandy', 2)]
[15]:
from sqlalchemy import desc, func
stmt = (
select(Address.user_id, func.count(Address.id).label("num_addresses"))
.group_by("user_id")
.order_by("user_id", desc("num_addresses"))
)
print(stmt)
SELECT address.user_id, count(address.id) AS num_addresses
FROM address GROUP BY address.user_id ORDER BY address.user_id, num_addresses DESC
ALIAS#
[16]:
from sqlalchemy.orm import aliased
address_alias_1 = aliased(Address)
address_alias_2 = aliased(Address)
print(
select(User)
.join_from(User, address_alias_1)
.where(address_alias_1.email_address == "patrick@aol.com")
.join_from(User, address_alias_2)
.where(address_alias_2.email_address == "patrick@gmail.com")
)
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account JOIN address AS address_1 ON user_account.id = address_1.user_id JOIN address AS address_2 ON user_account.id = address_2.user_id
WHERE address_1.email_address = :email_address_1 AND address_2.email_address = :email_address_2
Subconsultas#
[17]:
subq = select(Address).where(~Address.email_address.like("%@aol.com")).subquery()
address_subq = aliased(Address, subq)
stmt = (
select(User, address_subq)
.join_from(User, address_subq)
.order_by(User.id, address_subq.id)
)
with Session(engine) as session:
for user, address in session.execute(stmt):
print(f"{user} {address}")
User(id=1, name='spongebob', fullname='Spongebob Squarepants') Address(id=1, email_address='spongebob@sqlalchemy.org')
User(id=2, name='sandy', fullname='Sandy Cheeks') Address(id=2, email_address='sandy@sqlalchemy.org')
User(id=2, name='sandy', fullname='Sandy Cheeks') Address(id=3, email_address='sandy@squirrelpower.org')
[18]:
cte_obj = select(Address).where(~Address.email_address.like("%@aol.com")).cte()
address_cte = aliased(Address, cte_obj)
stmt = (
select(User, address_cte)
.join_from(User, address_cte)
.order_by(User.id, address_cte.id)
)
with Session(engine) as session:
for user, address in session.execute(stmt):
print(f"{user} {address}")
User(id=1, name='spongebob', fullname='Spongebob Squarepants') Address(id=1, email_address='spongebob@sqlalchemy.org')
User(id=2, name='sandy', fullname='Sandy Cheeks') Address(id=2, email_address='sandy@sqlalchemy.org')
User(id=2, name='sandy', fullname='Sandy Cheeks') Address(id=3, email_address='sandy@squirrelpower.org')
UNION#
[19]:
from sqlalchemy import union_all
stmt1 = select(User).where(User.name == "sandy")
stmt2 = select(User).where(User.name == "spongebob")
u = union_all(stmt1, stmt2)
[20]:
orm_stmt = select(User).from_statement(u)
with Session(engine) as session:
for obj in session.execute(orm_stmt).scalars():
print(obj)
User(id=2, name='sandy', fullname='Sandy Cheeks')
User(id=1, name='spongebob', fullname='Spongebob Squarepants')
[21]:
user_alias = aliased(User, u.subquery())
orm_stmt = select(user_alias).order_by(user_alias.id)
with Session(engine) as session:
for obj in session.execute(orm_stmt).scalars():
print(obj)
User(id=1, name='spongebob', fullname='Spongebob Squarepants')
User(id=2, name='sandy', fullname='Sandy Cheeks')