8.9. SQLAlchemy Core Result
.all()
.first()
.one()
- returns exactly one row.one_or_none()
8.9.1. SetUp
>>> from sqlalchemy import create_engine, MetaData, Table, Column
>>> from sqlalchemy import Integer, String, Date, Numeric, Enum
>>> from sqlalchemy import select
>>>
>>>
>>> engine = create_engine('sqlite:///:memory:', future=True)
>>> metadata = MetaData()
>>>
>>> astronaut = Table('astronaut', metadata,
... Column('id', Integer, primary_key=True),
... Column('firstname', String(50), nullable=False),
... Column('lastname', String(50), nullable=False),
... Column('agency', Enum('NASA', 'ESA', 'POLSA')),
... Column('birthdate', Date),
... Column('age', Integer),
... Column('height', Numeric(3,2)),
... Column('weight', Numeric(3,2)),
... )
>>>
>>> ASTRONAUTS = [
... {'firstname': 'Mark', 'lastname': 'Watney'},
... {'firstname': 'Melissa', 'lastname': 'Lewis'},
... {'firstname': 'Rick', 'lastname': 'Martinez'},
... ]
>>>
>>> with engine.begin() as db:
... metadata.create_all(db)
... result = db.execute(astronaut.insert(), ASTRONAUTS)
8.9.2. List[tuple]
It will download all the data from database
This technique is not particularly efficient for large databases
>>> query = select(astronaut.c.firstname, astronaut.c.lastname)
>>>
>>> with engine.begin() as db:
... result = db.execute(query)
>>>
>>> list(result)
[('Mark', 'Watney'),
('Melissa', 'Lewis'),
('Rick', 'Martinez')]
8.9.3. List[dict]
It will download all the data from database
This technique is not particularly efficient for large databases
>>> query = select(astronaut.c.firstname, astronaut.c.lastname)
>>>
>>> with engine.begin() as db:
... result = db.execute(query)
>>>
>>> list(result.mappings())
[{'firstname': 'Mark', 'lastname': 'Watney'},
{'firstname': 'Melissa', 'lastname': 'Lewis'},
{'firstname': 'Rick', 'lastname': 'Martinez'}]
8.9.4. One
Must be exactly one result, otherwise the exception is raised
Exception
MultipleResultsFound
>>> query = (
... select(astronaut.c.firstname, astronaut.c.lastname).
... where(astronaut.c.lastname == 'Watney')
... )
>>>
>>> with engine.begin() as db:
... result = db.execute(query)
>>>
>>> result.one()
('Mark', 'Watney')
8.9.5. One or None
>>> query = (
... select(astronaut.c.firstname, astronaut.c.lastname).
... where(astronaut.c.lastname == 'Watney')
... )
>>>
>>> with engine.begin() as db:
... result = db.execute(query)
>>>
>>> result.one_or_none()
('Mark', 'Watney')
8.9.6. All
>>> query = select(astronaut.c.firstname, astronaut.c.lastname)
>>>
>>> with engine.begin() as db:
... result = db.execute(query)
>>>
>>> result.all()
[('Mark', 'Watney'),
('Melissa', 'Lewis'),
('Rick', 'Martinez')]
8.9.7. First
Fetches the first result from a cursor object
CursorResult
object has no attribute 'last'
>>> query = select(astronaut.c.firstname, astronaut.c.lastname)
>>>
>>> with engine.begin() as db:
... result = db.execute(query)
>>>
>>> result.first()
('Mark', 'Watney')
8.9.8. Columns
Result objects now supports slicing at the result level. We can SELECT
some rows, and change the ordering and/or presence of columns after the fact
using .columns()
method [1]:
>>> query = (
... select(astronaut).
... order_by(astronaut.c.lastname)
... )
>>>
>>> with engine.begin() as db:
... result = db.execute(query)
>>>
>>> for lastname, firstname in result.columns('lastname', 'firstname'):
... print(f'{lastname=}, {firstname=}')
...
lastname='Lewis', firstname='Melissa'
lastname='Martinez', firstname='Rick'
lastname='Watney', firstname='Mark'
Note, that the .columns()
method defines the order for unpacked object.
It overwrites the default ordering from SELECT
clause.
8.9.9. Scalars
When you have a row, but there is only one column that you care about
We don't want the rows back, we want a list of values
A single column from the results can be delivered without using rows by
applying the .scalars()
modifier. This accepts and optional column name,
or otherwise assumes the first column:
>>> query = (
... select(astronaut.c.firstname).
... order_by(astronaut.c.lastname)
... )
>>>
>>> with engine.begin() as db:
... result = db.execute(query)
>>>
>>> result.scalars('firstname').all()
['Melissa', 'Rick', 'Mark']
Note, that for performance reasons we narrowed down the SELECT
clause
only to those values we want to receive.