Python Friday #76: CRUD With Metadata in SQLAlchemy Core

One of the benefits of SQLAlchemy is that it comes with an abstraction for SQL. Let’s find out how a bit of metadata can help us write much less database code.

This post is part of my journey to learn Python. You can find the other parts of this series here. You find the code for this post in my PythonFriday repository on GitHub.

 

Pre-requisites

To follow along, please make sure that you have SQLAlchemy installed and that you have the Northwind database for SQLite next to your Python script. I use engine.begin() instead of engine.connect() in my examples because this way we get a transaction back that cleans up the database should an exception occur.

 

Create the metadata

SQLAlchemy offers the objects MetaData, Table and Column to describe the tables we want to access. I find it especially helpful that we can describe only the columns we want to use and skip the rest. That allows us to write this code snipped to access the 4 columns we care about from the Employee table:

We can ask the metadata variable what it knows about our database with this snipped:

Table Employee:
Employee.Id (INTEGER)
Employee.LastName (VARCHAR(8000))
Employee.FirstName (VARCHAR(8000))
Employee.BirthDate (VARCHAR(8000))

 

Create (or insert)

With the metadata in place, our insert code works with Python objects and no longer needs any raw SQL statements:

First we create in insert() object that we connect to the metadata object for our table. On this object we set the values we want to insert as named arguments. Make sure that you write the column names exactly the same way as you used in the metadata.

To execute our Insert object, we need an engine and open up a transaction as we did in the raw SQL example. An important difference is that we now get a result back that contains in the attribute inserted_primary_key the value for the primary key of our newly created row.

 

Read (or select)

We can select an employee by its Id with this code:

We create a select() object and use the .where() method to specify which rows we want. In the example above I use employees.c.Id to tell SQLAlchemy that I want to match my parameter to the Id column (inside .c on the metadata object for your table is a list of all columns). Next week we take a deeper look at the different ways we can select rows in SQLAlchemy Core.

Since we search by the primary key, there is only one row that matches our where() and we can use the .first() method to get back the expected row (instead of a result set that we need to iterate over). Be aware that first() can return None if no row matches our select statement. Make sure that you put a check in place before you access values for an object that does not exist.

 

Update

We can update an employee with this code:

Our update() object gets the new values as named arguments and a .where() clause. If you do not specify which rows to update, SQLAlchemy will update every row in your database.

 

Delete

We can delete an employee with this code:

As with the update() object, make sure that your delete() object always gets a .where() clause. Otherwise you delete all rows in your table.

 

Next

SQLAlchemy Core with metadata lets us access our database without the need to write SQL statements. We still need to know the operations and define a where clause, but the code we write is on a much higher abstraction level. Next week we look at filters and how we can combine them to get back exactly the rows we want.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.