56

Is it possible to do SELECT * in SQLAlchemy?

Specifically, SELECT * WHERE foo=1?

Smi
  • 13,850
  • 9
  • 56
  • 64
mike
  • 46,876
  • 44
  • 102
  • 112

11 Answers11

56

Is no one feeling the ORM love of SQLAlchemy today? The presented answers correctly describe the lower-level interface that SQLAlchemy provides. Just for completeness, this is the more-likely (for me) real-world situation where you have a session instance and a User class that is ORM mapped to the users table.

for user in session.query(User).filter_by(name='jack'):
     print(user)
     # ...

And this does an explicit select on all columns.

Smart Manoj
  • 5,230
  • 4
  • 34
  • 59
Ali Afshar
  • 40,967
  • 12
  • 95
  • 109
  • 2
    I think the reason mike asked about `SELECT *` specifically is to get a sequence of column values. A full solution using the ORM would be to get the User objects as above, then find a way of iterating over columns as discussed at http://stackoverflow.com/questions/2537471/method-of-iterating-over-sqlalchemy-models-defined-columns. – Mu Mind Sep 28 '12 at 01:20
  • 1
    what if I join two models and want all the resulting columns? – Chris2048 Jul 09 '19 at 10:37
  • What if `Select * from` is in a subquery? – MattSom Jun 05 '20 at 19:48
  • @mattsom you can use select(*subq.c) see my answer below – Piotr Czapla Aug 27 '21 at 08:37
  • This was the answer for me in conjunction with the addition of `__str__` method defined on my table class for printing out the columns to my taste (I only wanted to inspect for sanity check). – hi2meuk Nov 09 '21 at 20:20
  • old answer, no longer valid in 1.4 – the1gofer Apr 14 '22 at 15:20
36

The following selection works for me in the core expression language (returning a RowProxy object):

foo_col = sqlalchemy.sql.column('foo')
s = sqlalchemy.sql.select(['*']).where(foo_col == 1)
Ryne Everett
  • 6,427
  • 3
  • 37
  • 49
14

If you don't list any columns, you get all of them.

query = users.select()
query = query.where(users.c.name=='jack')
result = conn.execute(query)
for row in result:
    print row

Should work.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
11

You can always use a raw SQL too:

str_sql = sql.text("YOUR STRING SQL")
#if you have some args:
args = {
    'myarg1': yourarg1
    'myarg2': yourarg2}
#then call the execute method from your connection
results = conn.execute(str_sql,args).fetchall()
Fernando Freitas Alves
  • 3,709
  • 3
  • 26
  • 45
10

Where Bar is the class mapped to your table and session is your sa session:

bars = session.query(Bar).filter(Bar.foo == 1)
adam
  • 6,582
  • 4
  • 29
  • 28
9

Turns out you can do:

sa.select('*', ...)
mike
  • 46,876
  • 44
  • 102
  • 112
8

I had the same issue, I was trying to get all columns from a table as a list instead of getting ORM objects back. So that I can convert that list to pandas dataframe and display.

What works is to use .c on a subquery or cte as follows:

U = select(User).cte('U')
stmt = select(*U.c)
rows = session.execute(stmt)

Then you get a list of tuples with each column.

Another option is to use __table__.columns in the same way:

stmt = select(*User.__table__.columns)
rows = session.execute(stmt)

In case you want to convert the results to dataframe here is the one liner:

pd.DataFrame.from_records(rows, columns=rows.keys())
Piotr Czapla
  • 25,734
  • 24
  • 99
  • 122
4

For joins if columns are not defined manually, only columns of target table are returned. To get all columns for joins(User table joined with Group Table:

sql = User.select(from_obj(Group, User.c.group_id == Group.c.id))
# Add all coumns of Group table to select
sql = sql.column(Group)
session.connection().execute(sql)
derkan
  • 475
  • 4
  • 5
4

I had the same issue, I was trying to get all columns from a table as a list instead of getting ORM objects back. So that I can convert that list to pandas dataframe and display.

What works is to use .c on a subquery or cte as follows:

U = select(User).cte('U')
stmt = select(*U.c)
rows = session.execute(stmt)

Then you get a list of tuples with each column.

Another option is to use __table__.columns in the same way:

stmt = select(*User.__table__.columns)
rows = session.execute(stmt)

In case you want to convert the results to dataframe here is the one liner:

pd.DataFrame.from_records(dict(zip(r.keys(), r)) for r in rows)
Piotr Czapla
  • 25,734
  • 24
  • 99
  • 122
3

If you're using the ORM, you can build a query using the normal ORM constructs and then execute it directly to get raw column values:

query = session.query(User).filter_by(name='jack')
for cols in session.connection().execute(query):
    print cols
Mu Mind
  • 10,935
  • 4
  • 38
  • 69
  • 3
    If you already have a `session` object that you used to get the query, why are you using the connection's `execute`? You can just do - `for user in query: print user.name, user.age` – Guy Feb 14 '17 at 11:11
2
every_column = User.__table__.columns
records = session.query(*every_column).filter(User.foo==1).all()

When a ORM class is passed to the query function, e.g. query(User), the result will be composed of ORM instances. In the majority of cases, this is what the dev wants and will be easiest to deal with--demonstrated by the popularity of the answer above that corresponds to this approach.

In some cases, devs may instead want an iterable sequence of values. In these cases, one can pass the list of desired column objects to query(). This answer shows how to pass the entire list of columns without hardcoding them, while still working with SQLAlchemy at the ORM layer.

Stew
  • 4,495
  • 6
  • 31
  • 41