SQL Expression Language
last modified July 6, 2020
In this part of the SQLAlchemy tutorial, we work with SQLAlchemy's SQL Expression Language.
The SQLAlchemy Expression Language represents relational database structures and expressions using Python constructs. The expression language improves the maintainability of the code by hiding the SQL language and thus allowing not to mix Python code and SQL code.
The Object Relational Mapper, ORM, is built on top of the expression language.
Selecting all rows
In the first example, we use the expression language to select all rows from a table.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Table, MetaData
from sqlalchemy.sql import select
eng = create_engine('sqlite:///test.db')
with eng.connect() as con:
meta = MetaData(eng)
cars = Table('Cars', meta, autoload=True)
stm = select([cars])
rs = con.execute(stm)
print rs.fetchall()
The example uses the select method to retrieve all rows from
the Cars table.
meta = MetaData(eng)
cars = Table('Cars', meta, autoload=True)
We load the definition of the Cars table.
stm = select([cars])
With the select method, we create an SQL SELECT
statement. This particular expression selects all columns and rows from
the provided table.
rs = con.execute(stm)
The statement is executed.
print rs.fetchall()
With the fetchall method, we print all returned data.
$ ./exp_select_all.py [(1, u'Audi', 52642), (2, u'Mercedes', 57127), (3, u'Skoda', 9000), (4, u'Volvo', 29000), (5, u'Bentley', 350000), (6, u'Citroen', 21000), (7, u'Hummer', 41400), (8, u'Volkswagen', 21600)]
This is the output of the example.
Limiting selected output
In the second example, we limit the data retrieved from the table.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Table, MetaData
from sqlalchemy.sql import select
eng = create_engine('sqlite:///test.db')
with eng.connect() as con:
meta = MetaData(eng)
cars = Table('Cars', meta, autoload=True)
stm = select([cars.c.Name, cars.c.Price]).limit(3)
rs = con.execute(stm)
print rs.fetchall()
The example prints two columns of three rows from the Cars table.
stm = select([cars.c.Name, cars.c.Price]).limit(3)
Between the square brackets, we provide the columns that we want
to be displayed. The limit method limits the result set to three rows.
$ ./exp_select_limit.py [(u'Audi', 52642), (u'Mercedes', 57127), (u'Skoda', 9000)]
This is the output of the exp_select_limit.py program.
The where() method
The where method adds a WHERE clause to the
statement generated by the select method.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Table, MetaData
from sqlalchemy.sql import select, and_
eng = create_engine('sqlite:///test.db')
with eng.connect() as con:
meta = MetaData(eng)
cars = Table('Cars', meta, autoload=True)
stm = select([cars]).where(and_(cars.c.Price > 10000,
cars.c.Price < 40000))
rs = con.execute(stm)
print rs.fetchall()
The example selects all cars whose price is between 10000 and 40000.
stm = select([cars]).where(and_(cars.c.Price > 10000,
cars.c.Price < 40000))
To build the expected SQL statement, we use the select and where
methods and the and_ operator.
$ ./exp_select_where.py [(4, u'Volvo', 29000), (6, u'Citroen', 21000), (8, u'Volkswagen', 21600)]
The code example prints all Cars with prices between 10000 and 40000.
The like() method
The like method adds a LIKE clause to the
statement generated by the select method.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Table, MetaData
from sqlalchemy.sql import select
eng = create_engine('sqlite:///test.db')
with eng.connect() as con:
meta = MetaData(eng)
cars = Table('Cars', meta, autoload=True)
stm = select([cars]).where(cars.c.Name.like('%en'))
rs = con.execute(stm)
print rs.fetchall()
With the like method, we select all cars
whose name ends with 'en'.
stm = select([cars]).where(cars.c.Name.like('%en'))
The like method is applied on the column name.
$ ./exp_select_like.py [(6, u'Citroen', 21000), (8, u'Volkswagen', 21600)]
There are two cars with names ending in 'en'.
Ordering rows
The order_by method adds a ORDER BY clause to the
statement generated by the select method.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Table, MetaData
from sqlalchemy.sql import select, asc
eng = create_engine('sqlite:///test.db')
with eng.connect() as con:
metadata = MetaData(eng)
cars = Table('Cars', metadata, autoload=True)
s = select([cars]).order_by(asc(cars.c.Name))
rs = con.execute(s)
for row in rs:
print row['Id'], row['Name'], row['Price']
The example prints all rows ordered by cars' names.
s = select([cars]).order_by(asc(cars.c.Name))
The order_by methos is given the asc operator,
which makes the ordering in ascending way.
$ ./exp_select_order.py 1 Audi 52642 5 Bentley 350000 6 Citroen 21000 7 Hummer 41400 2 Mercedes 57127 3 Skoda 9000 8 Volkswagen 21600 4 Volvo 29000
The example prints all rows. The rows are arranged in ascending order by the cars' names.
The in_() operator
The in_ operator is used to add IN clause
to the generated SELECT statement.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Table, MetaData, tuple_
from sqlalchemy.sql import select
eng = create_engine('sqlite:///test.db')
with eng.connect() as con:
meta = MetaData(eng)
cars = Table('Cars', meta, autoload=True)
k = [(2,), (4,), (6,), (8,)]
stm = select([cars]).where(tuple_(cars.c.Id).in_(k))
rs = con.execute(stm)
for row in rs:
print row['Id'], row['Name'], row['Price']
The example prints four rows of the table, specified by
the in_ operator.
stm = select([cars]).where(tuple_(cars.c.Id).in_(k))
With the help of the tuple_ and in_
operators, we build the statement containing the IN
clause.
$ ./exp_select_in.py 2 Mercedes 57127 4 Volvo 29000 6 Citroen 21000 8 Volkswagen 21600
This is the output of the example.
Creating a table
The next example creates a table in memory using the expression language.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from sqlalchemy import (create_engine, Table, Column, Integer,
String, MetaData)
from sqlalchemy.sql import select
eng = create_engine('sqlite:///:memory:')
with eng.connect() as con:
meta = MetaData(eng)
cars = Table('Cars', meta,
Column('Id', Integer, primary_key=True),
Column('Name', String),
Column('Price', Integer)
)
cars.create()
ins1 = cars.insert().values(Id=1, Name='Audi', Price=52642)
con.execute(ins1)
ins2 = cars.insert().values(Id=2, Name='Mercedes', Price=57127)
con.execute(ins2)
ins3 = cars.insert().values(Id=3, Name='Skoda', Price=6000)
con.execute(ins3)
s = select([cars])
rs = con.execute(s)
for row in rs:
print row['Id'], row['Name'], row['Price']
The example creates a new table in memory, fills it with data, and
executes a SELECT statement on the table.
eng = create_engine('sqlite:///:memory:')
The created table will be SQLite's in-memory table.
meta = MetaData(eng)
cars = Table('Cars', meta,
Column('Id', Integer, primary_key=True),
Column('Name', String),
Column('Price', Integer)
)
We provide the definition of the table.
cars.create()
The table is created using the create method.
ins1 = cars.insert().values(Id=1, Name='Audi', Price=52642) con.execute(ins1)
With the insert method, we insert a new row
into the table.
s = select([cars])
rs = con.execute(s)
for row in rs:
print row['Id'], row['Name'], row['Price']
In the final step, we execute a SELECT statement and
print all the returned data to the console.
$ ./exp_create_table.py 1 Audi 52642 2 Mercedes 57127 3 Skoda 6000
This is the output of the example.
Joining tables
In the following example, we join fields from two tables.
We use the join method.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from sqlalchemy import (create_engine, Table, Column, Integer,
String, ForeignKey, MetaData)
from sqlalchemy.sql import select
eng = create_engine('sqlite:///test.db')
with eng.connect() as con:
meta = MetaData(eng)
authors = Table('Authors', meta, autoload=True)
books = Table('Books', meta, autoload=True)
stm = select([authors.join(books)])
rs = con.execute(stm)
for row in rs:
print row['Name'], row['Title']
The example executes an inner join on two tables. We get authors and their corresponding titles.
authors = Table('Authors', meta, autoload=True)
books = Table('Books', meta, autoload=True)
The two tables are loaded from the database.
stm = select([authors.join(books)])
We create a SELECT statement with a JOIN
clause.
$ ./exp_join_tables.py Jane Austen Emma Leo Tolstoy War and Peace Joseph Heller Catch XII Charles Dickens David Copperfield Joseph Heller Good as Gold Leo Tolstoy Anna Karenia
This is the output of the example.
In this part of the SQLAlchemy tutorial, we worked with SQL Expression Language.