@@ -425,22 +425,66 @@ in the same way as if we had used ``user_table`` directly::
425425 {opensql}SELECT user_account.id, user_account.name, user_account.fullname
426426 FROM user_account
427427
428- To select from individual columns using ORM entities, the class-bound
429- attributes can be passed directly which are resolved into the
428+ When executing a statement like the above using the ORM :meth: `_orm.Session.execute `
429+ method, there is an important difference when we select from a full entity
430+ such as ``User ``, as opposed to ``user_table ``, which is that the **entity
431+ itself is returned as a single column within each row **. That is, when we fetch rows from
432+ the above statement, as there is only the ``User `` entity in the list of
433+ things to fetch, we get back :class: `_engine.Row ` objects that have only one column, which contain
434+ instances of the ``User `` class::
435+
436+ >>> row = session.execute(select(User)).first()
437+ {opensql}BEGIN...
438+ SELECT user_account.id, user_account.name, user_account.fullname
439+ FROM user_account
440+ [...] (){stop}
441+ >>> row
442+ (User(id=1, name='spongebob', fullname='Spongebob Squarepants'),)
443+
444+ The above :class: `_engine.Row ` has just one column, representing the ``User `` entity::
445+
446+ >>> row[0]
447+ User(id=1, name='spongebob', fullname='Spongebob Squarepants')
448+
449+ Alternatively, we can select individual columns from an ORM entity, by
450+ using the class-bound
451+ attributes; when these are passed to a construct such as :func: `_sql.select `,
452+ they are resolved into the
430453:class: `_schema.Column ` or other SQL expression represented by each attribute::
431454
432455 >>> print(select(User.name, User.fullname))
433456 {opensql}SELECT user_account.name, user_account.fullname
434457 FROM user_account
435458
436- .. tip ::
459+ When we invoke *this * statement using :meth: `_orm.Session.execute `, we now
460+ receive rows that have individual columns per value::
461+
462+ >>> row = session.execute(select(User.name, User.fullname)).first()
463+ {opensql}SELECT user_account.name, user_account.fullname
464+ FROM user_account
465+ [...] (){stop}
466+ >>> row
467+ ('spongebob', 'Spongebob Squarepants')
468+
469+ The approaches can also be mixed, as below where we SELECT the ``name ``
470+ attribute of the ``User `` entity as the first column, and combine it with full
471+ ``Address `` entities in the second column::
472+
473+ >>> session.execute(
474+ ... select(User.name, Address).
475+ ... where(User.id==Address.user_id).
476+ ... order_by(Address.id)
477+ ... ).all()
478+ {opensql}SELECT user_account.name, address.id, address.email_address, address.user_id
479+ FROM user_account, address
480+ WHERE user_account.id = address.user_id ORDER BY address.id
481+ [...] (){stop}
482+ [('spongebob', Address(id=1, email_address='spongebob@sqlalchemy.org')),
483+ ('sandy', Address(id=2, email_address='sandy@sqlalchemy.org')),
484+ ('sandy', Address(id=3, email_address='sandy@squirrelpower.org'))]
437485
438- When ORM-related objects are used within the :class: `_sql.Select `
439- construct, they are resolved into the underlying :class: `_schema.Table ` and
440- :class: `_schema.Column ` and similar Core constructs they represent; at the
441- same time, they apply a **plugin ** to the core :class: `_sql.Select `
442- construct such that a new set of ORM-specific behaviors make take
443- effect when the construct is being compiled.
486+ Approaches towards selecting ORM entities and columns as well as common methods
487+ for converting rows are discussed further at :ref: `orm_queryguide_select_columns `.
444488
445489.. seealso ::
446490
0 commit comments