Simeon Simeonov
SQLAlchemy is a Python library created by Mike Bayer to provide a high-level Pythonic interface to RDBMS such as PostgreSQL, SQLite, MySQL, Oracle, DB2.
SQLAlchemy includes RDBMS-independent SQL expression language and an object-relational mapper (ORM).
portability - the programming interface is independent of the type of RDBMS and connector used
security - no more SQL injections
abstraction - no need to bother with complex JOINs
object-orientation - you work with objects and NOT tables and rows
performance - exploits the likehood of reusing a particular query
flexibility - you can override almost anything
SQLAlchemy consists of several components, including the SQL expression language and the ORM.
In order to enable these components, SQLAlchemy also provides an Engine class and MetaData class.
SQLAlchemy gives us the choice between classical mapping and the newer declarative mapping
import sqlalchemy
sqlalchemy.__version__
from sqlalchemy import create_engine
# engine = create_engine("postgresql+psycopg2://user:zipassword@localhost/mydb" , echo=True)
# The string form of the URL is dialect+driver://user:password@host/dbname[?key=value..],
# where dialect is a database name such as mysql, oracle, postgresql, etc.,
# and driver the name of a DBAPI, such as psycopg2, pyodbc, cx_oracle
# The echo flag is a shortcut to setting up SQLAlchemy logging,
# which is accomplished via Python’s standard logging module.
# With it enabled, we’ll see all the generated SQL produced.
# engine = create_engine("sqlite:///library.db", echo=True)
engine = create_engine("sqlite:///:memory:", echo=True)
metadata = MetaData()
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
authors_table = Table(
"authors",
metadata,
Column("id", Integer, primary_key=True),
Column("name", String),
) # Column("name", String(50)) is possible
books_table = Table(
"books",
metadata,
Column("id", Integer, primary_key=True),
Column("title", String),
Column("description", String),
Column("author_id", ForeignKey('authors.id')),
)
metadata.create_all(engine) # creates the tables
insert_stmt = authors_table.insert(bind=engine)
type(insert_stmt)
# Out: <class 'sqlalchemy.sql.expression.Insert'>
print(insert_stmt)
# Out: INSERT INTO authors (id, name) VALUES (:id,:name)
compiled_stmt = insert_stmt.compile()
print(compiled_stmt.params)
# Out: {'id': None, 'name': None}
insert_stmt.execute(name="Alexandre Dumas") # insert a single entry
insert_stmt.execute([{"name": 'Mr X'},{'name': 'Mr Y'}]) # a list of entries
metadata.bind = engine # no need to explicitly bind the engine from now on
select_stmt = authors_table.select(authors_table.c.id==2)
result = select_stmt.execute()
result.fetchall()
# Out: [(1, u'Mr X')]
del_stmt = authors_table.delete()
del_stmt.execute(whereclause=text("name='Mr Y'"))
del_stmt.execute() # delete all
from sqlalchemy.orm import mapper
from sqlalchemy.orm import relationship, backref
class Author:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
class Book:
def __init__(self, title, description, author):
self.title = title
self.description = description
self.author = author
def __str__(self):
return self.title
mapper(Book, books_table)
mapper(Author, authors_table, properties = {"books": relation(Book, backref="author")})
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref
Base = declarative_base()
class Author(Base):
__tablename__ = "authors"
id = Column(Integer, primary_key=True)
name = Column(String)
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
class Book(Base):
__tablename__ = "books" # self.__table__ will be available for our objects
id = Column(Integer, primary_key=True)
title = Column(String)
description = Column(String)
author_id = Column(Integer, ForeignKey("authors.id"))
author = relationship(Author, backref=backref("books", order_by=title))
def __init__(self, title, description, author):
self.title = title
self.description = description
self.author = author
def __str__(self):
return self.title
Base.metadata.create_all(engine)# create tables
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine) # bound session
session = Session()
author_1 = Author("Richard Dawkins")
author_2 = Author("Matt Ridley")
book_1 = Book("The Red Queen", "A popular science book", author_2)
book_2 = Book("The Selfish Gene", "A popular science book", author_1)
book_3 = Book("The Blind Watchmaker", "The theory of evolutio", author_1) # typo
session.add(author_1)
session.add(author_2)
session.add(book_1)
session.add(book_2)
session.add(book_3) # or simply session.add_all([author_1, author_2, book_1, book_2, book_3])
# session.flush()
session.commit() # flushes (issues the statements and sends them to the RDBMS) and commits
book_3.description = "The theory of evolution" # update the object
book_3 in session # check whether the object is in the session
# Out: True
session.commit()
session.query(Book).order_by(Book.id) # returns a Query instance with a .statement attribute
session.query(Book).order_by(Book.id).all() # returns an object-list
# return all book objects where title == "The Selfish Gene"
session.query(Book).filter(Book.title == "The Selfish Gene").order_by(Book.id).all()
# using LIKE
session.query(Book).filter(Book.title.like("The%")).order_by(Book.id).all()
query = session.query(Book).filter(Book.id == 9).order_by(Book.id)
query.count() # returns 0L
query.all() # returns an empty list
query.first() # returns None
query.one() # raises NoResultFound exception
query = session.query(Book).filter(Book.id == 1).order_by(Book.id)
book_1 = query.one()
book_1.description # returns "A popular science book"
book_1.author.books # returns a list of Book-objects representing all the books from the same author.
# get a list of all Book-instances where the author"s name is "Richard Dawkins"
session.query(Book).filter(Book.author_id == Author.id).filter(Author.name == "Richard Dawkins").all()
session.query(Book).join(Author).filter(Author.name == "Richard Dawkins").all()
session.query(Book).\
from_statement("SELECT b.* FROM books b, authors a WHERE b.author_id = a.id AND a.name=:name").\
params(name="Richard Dawkins").all()
https://gitlab.fifty.eu/odin/data-science/odin-data-access
Provides the odin_data_access module with some of the following entities:
The DBTableAccessor:
Now watch this well-rehearsed demo...