☰
Python Across Disciplines
with Python + AI Tool   
×
Table of Contents

1.1.   Introduction 1.2.   About the Author & Contact Info 1.3.   Book Conventions 1.4.   What (Who) is a Programmer? 1.5.   Programming Across Disciplines 1.6.   Foundational Computing Concepts 1.7.   About Python 1.8.   First Steps 1.8.1 Computer Setup 1.8.2 Python print() Function 1.8.3 Comments
2.1. About Data 2.2. Data Types 2.3. Variables 2.4. User Input 2.5. Data Structures (DS)         2.5.1. DS Concepts         2.5.2. Lists         2.5.3. Dictionaries         2.5.4. Others 2.6. Files         2.6.1. Files & File Systems         2.6.2. Python File Object         2.6.3. Data Files 2.7. Databases
3.1. About Processing 3.2. Decisions         3.2.1 Decision Concepts         3.2.2 Conditions & Booleans         3.2.3 if Statements         3.2.4 if-else Statements         3.2.5 if-elif-else Statements         3.2.6 In-Line if Statements 3.3. Repetition (a.k.a. Loops)         3.3.1  Repetition Concepts         3.3.2  while Loops         3.3.3  for Loops         3.3.4  Nested Loops         3.3.5  Validating User Input 3.4. Functions         3.4.1  Function Concepts         3.4.2  Built-In Functions         3.4.3  Programmer Defined Functions 3.5. Libraries         3.5.1  Library Concepts         3.5.2  Standard Library         3.5.3  External Libraries 3.6. Processing Case Studies         3.6.1  Case Studies         3.6.2  Parsing Data
4.1. About Output 4.2. Advanced Printing 4.3. Data Visualization   4.4  Sound
  4.5  Graphics
  4.6  Video
  4.7  Web Output
  4.8  PDFs & Documents
  4.9  Dashboards
  4.10  Animation & Games
  4.11  Text to Speech

5.1 About Disciplines 5.2 Accounting 5.3 Architecture 5.4 Art 5.5 Artificial Intelligence (AI) 5.6 Autonomous Vehicles 5.7 Bioinformatics 5.8 Biology 5.9 Bitcoin 5.10 Blockchain 5.11 Business 5.12 Business Analytics 5.13 Chemistry 5.14 Communication 5.15 Computational Photography 5.16 Computer Science 5.17 Creative Writing 5.18 Cryptocurrency 5.19 Cultural Studies 5.20 Data Analytics 5.21 Data Engineering 5.22 Data Science 5.23 Data Visualization 5.24 Drone Piloting 5.25 Economics 5.26 Education 5.27 Engineering 5.28 English 5.29 Entrepreneurship 5.30 Environmental Studies 5.31 Exercise Science 5.32 Film 5.33 Finance 5.34 Gaming 5.35 Gender Studies 5.36 Genetics 5.37 Geography 5.38 Geology 5.39 Geospatial Analysis ☯ 5.40 History 5.41 Humanities 5.42 Information Systems 5.43 Languages 5.44 Law 5.45 Linguistics 5.46 Literature 5.47 Machine Learning 5.48 Management 5.49 Marketing 5.50 Mathematics 5.51 Medicine 5.52 Military 5.53 Model Railroading 5.54 Music 5.55 Natural Language Processing (NLP) 5.56 Network Analysis 5.57 Neural Networks 5.58 Neurology 5.59 Nursing 5.60 Pharmacology 5.61 Philosophy 5.62 Physiology 5.63 Politics 5.64 Psychiatry 5.65 Psychology 5.66 Real Estate 5.67 Recreation 5.68 Remote Control (RC) Vehicles 5.69 Rhetoric 5.70 Science 5.71 Sociology 5.72 Sports 5.73 Stock Trading 5.74 Text Mining 5.75 Weather 5.76 Writing
6.1. Databases         6.1.1 Overview of Databases         6.1.2 SQLite Databases         6.1.3 Querying a SQLite Database         6.1.4 CRUD Operations with SQLite         6.1.5 Connecting to Other Databases
Built-In Functions Conceptss Data Types Date & Time Format Codes Dictionary Methods Escape Sequences File Access Modes File Object Methods Python Keywords List Methods Operators Set Methods String Methods Tuple Methods Glossary Index Appendices   Software Install & Setup
  Coding Tools:
  A.  Python    B.  Google CoLaboratory    C.  Visual Studio Code    D.  PyCharm IDE    E.  Git    F.  GitHub 
  Database Tools:
  G.  SQLite Database    H.  MySQL Database 


Python Across Disciplines
by John Gordon © 2023

Table of Contents

Table of Contents  »  Chapter 6.1.3 : Querying a SQLite Database

Querying a SQLite Database
Subscribe Contact


Contents

Overview

Interacting with a database from a programming language is a critical skill for programmers to learn. We do this in all mannger of applications, such as web pages, desktop applications, mobile device applications, enterprise and server applications, and many other categories. Programmers write code to interact with databases behind all of these types of applications. The most common action programmers write in these contexts are queries.

Here's an example, let's say we've written an application that requires users to log in through a Graphic User Interface (GUI). When a user attempts to log into the application the program needs to confirm the user's login and password are valid. The programmer does this by comparing the login and password entered by the user with a user record stored in a database. A simplified image of this process might look like this:



Figure 1: Example of Application + Code + Database

In this example, the user types their login and password and clicks the Login button. The program creates a query that includes the login and password provided by the user and sends that query to the database engine. We can think of this as asking the database a question, in this example we might verbalize the question as Is there a user in the database with this login and password combination? The result of the question (query) to the database is returned to the program as a result set, which may contain a result or not. In this example, if there is not a result then there is no user record that matches the login and password entered by the user. So, in that case, the program would inform the user their login and/or password are invalid. Otherwise, since there is a user with the login and password combination so the login is successful and the program would then allow the user into the system.

That example demonstrates, at a high level, how the programmer uses SQL queries to ask the database a question (query) and then respond to the response to that question.

How to Query a Database in Python?

In order to ask a question of the database, that is, send it a query, from within a Python program, we embed SQL query code in our Python program and instruct Python to pass that query to the database engine. This is often referred to as embedded SQL. The database engine processes the SQL query and returns a result set to the Python program. Once the result set is returned, we can then use Python code to work with that result as we need to depending on the context of the program.

A common approach to getting the SQL part of this process working correctly is to write the SQL in our database IDE, instead of directly in Python, at first. In this way, we can confirm that our SQL query produces the results we need and then we can copy the SQL code from the database IDE over into our Python programming environment. For example, let's take one of the queries from the DemoQueries.sql script file we looked at previously.

First, I'll open SQLite Studio and open the DemoQueries.sql file:



Figure 2: SQLite Studio and DemoQueries.sql File

Note that I have highlighted one of the queries. This query asks the question Are there any students whose last name is Summers? If I click the Run button I see the following result:



Figure 3: DemoQueries.sql Query Results Set

The result set indicates that there is one student with the last name Summers. Also, because the query reads SELECT * it means we're asking for all columns in the students table to be part of our result set.

In the next section, we'll take a look at how to bring the SQL into Python and work with the query results.

How to Setup a Python Program for SQLite Interaction

To interact with SQLite in Python there are a few key concepts to understand that's we'll cover here before looking at a full code example. Take a look at the following partial Python code file and read the detailed notes below. You can use it as a template for interacting with a SQLite database from Python.



Figure 4: Template Code for Interacting with Database in Python
Notes


Example 1

Now let's take a look at a full code example. We'll use the query that we considered above: SELECT * FROM students WHERE last_name = 'Summers';". We know from testing that query in SQLite Studio that it returns at least one student record. So, using the template example above, we'll implement that query here:

Python Code
import sqlite3
connection = sqlite3.connect("c:\SQLite\Data\grading_system.db")
cursor = connection.execute("SELECT * FROM Students WHERE last_name = 'Summers';")
for row in cursor:
    print("Student ID:", row[0])
    print("First Name:", row[1])
    print("Last Name:", row[2])
    print("Class Standing:", row[3])
    print("School ID:", row[4])
    print("Cumulative GPA:", row[5])
    print("Major ID:", row[6])
connection.close()
Output
Student ID: 27
First Name: Amelia
Last Name: Summers
Class Standing: Junior
School ID: S28816323
Cumulative GPA: 3.44
Major ID: 8
Notes

This code example works fine and demonstrates how to use the template above to query a database table. Also, it works fine for a query that results in just one record, however what if our result set has multiple records? The output would not be ideal. When result sets contain multiple records it is more common to print them in columnar format, that is, in rows and columns. Example 2 demonstrates this approach.



Example 2

In this second example, first we'll return to SQLite Studio and test a different query. This time we'll use SELECT * FROM students WHERE last_name IN ('Cooper', 'Summers'); which will give us a result set with three student records, as seen here:



Figure 5: Example of Last Name Query

In Python, we'll use the same code as Example 1, except we'll replace the query statement to the new one:

Python Code
import sqlite3
connection = sqlite3.connect("c:\SQLite\Data\grading_system.db")
cursor = connection.execute("SELECT * FROM Students WHERE last_name IN ('Cooper', 'Summers');")
for row in cursor:
    print("Student ID:", row[0])
    print("First Name:", row[1])
    print("Last Name:", row[2])
    print("Class Standing:", row[3])
    print("School ID:", row[4])
    print("Cumulative GPA:", row[5])
    print("Major ID:", row[6])
connection.close()
Notes
Output
Student ID: 27
First Name: Amelia
Last Name: Summers
Class Standing: Junior
School ID: S28816323
Cumulative GPA: 3.44
Major ID: 8
Student ID: 68
First Name: Kendra
Last Name: Cooper
Class Standing: Senior
School ID: S35743296
Cumulative GPA: 4
Major ID: 27
Student ID: 184
First Name: Patricia
Last Name: Cooper
Class Standing: Senior
School ID: S40063558
Cumulative GPA: 4
Major ID: 25
Notes
Refactored Python Code
import sqlite3
connection = sqlite3.connect("c:\SQLite\Data\grading_system.db")
cursor = connection.execute("SELECT * FROM Students WHERE last_name IN ('Cooper', 'Summers');")
print("-" * 50)
print("ID\t\tName\t\tClass\tGPA")
print("-" * 50)
for row in cursor:
    print(row[4] + "\t" + row[1] + " " + row[2] + "\t" + row[3] + "\t" + str(row[5]))
print("-" * 50)
connection.close()
Output
--------------------------------------------------
ID              Name            Class   GPA
--------------------------------------------------
S28816323       Amelia Summers  Junior  3.44
S35743296       Kendra Cooper   Senior  4.00
S40063558       Patricia Cooper Senior  4.00
--------------------------------------------------
Notes


SQL Code or Python Code?

Now that we've seen a couple of simple examples of embedded SQL in Pytyon, a key factor in deciding how to build database-driven applications is where does the logic belong? That is, what belongs in the SQL code and what belongs in the Python code?

In general, the SQL code should be used to take advantage of the database engine's strengths of working with sets of data. Take the last query we used above for example: SELECT * FROM students WHERE last_name IN ('Cooper', 'Summers');. This query takes advantage of the database engine and very quickly finds three student records that match the critieria based on last name. If we had to do that same thing with Python, it would be row by row which would be very inefficient.

Given the power of the database engine, one of the challenges for programmers is to learn how to take advantage of that power, which means learning as much about SQL coding as possible. There are many free resources available for learning SQL online.

On the other hand, our Python code handles all aspects of our application, including coordinating the embedded SQL with the database engine and then taking the appropriate action(s) on the result sets from the database. In Example 2, that means printing a well-formatted report of the results.

Let's consider a further example with the SQL Code or Python Code? question in mind. Let's say we are asked to modify Example 2 above so that our printed report is sorted last name and then first name. Looking at the output we see that it is not in that order currently. Where do we change that--in the SQL code or the Python code?

We could make this change in either SQL or Python, but which is more efficient? Sorting the result set is best accomplished in the SQL code because the database engine is very well suited to accomplish that task and the code change is minimal. We can simply add an ORDER BY clause to the embedded SQL query. Nothing else about our program would have to change, like this ...

Refactored Python Code
import sqlite3
connection = sqlite3.connect("c:\SQLite\Data\grading_system.db")
cursor = connection.execute("SELECT * FROM Students WHERE last_name IN ('Cooper', 'Summers') ORDER BY last_name, first_name;")
print("-" * 50)
print("ID\t\tName\t\tClass\tGPA")
print("-" * 50)
for row in cursor:
    print(row[4] + "\t" + row[1] + " " + row[2] + "\t" + row[3] + "\t" + str(row[5]))
print("-" * 50)
connection.close()
Output
--------------------------------------------------
ID              Name            Class   GPA
--------------------------------------------------
S35743296       Kendra Cooper   Senior  4.00
S40063558       Patricia Cooper Senior  4.00
S28816323       Amelia Summers  Junior  3.44
--------------------------------------------------
Notes

This is a simple example of deciding where to implement changes to database-driven applications.



Embedded SQL + Python Variables

So far the embedded SQL we've seen has been fully hardcoded, that is, it will always run the same way. However, it is more common that there are conditions that need to be considered as part of what we want to query in the database.

Let's consider or first query above SELECT * FROM students WHERE last_name = 'Summers';". This query will always look for students with the last name Summers. This is not very flexible, what if I want to see all students with other last names? We can combined our embedded SQL with Python variables to create dynamic embedded SQL. In this manner, we can make our application very flexible and more powerful.

Let's consider a version of example above that uses dynamic SQL...



Dynamic SQL Example

In the examples above our query had the last name hardcoded in the SQL query code. It is more common that we would want the query to be dynamic in Python, that is, we want to allow the user to be able to enter a last name and the query will ask the database engine for all students with that last name.

To accomplish this, we can use the similar code as above, but with an added user prompt to enter a name and then a change to the query to be dynamic, that is, using the name entered by the user each time.

Here's the refactored code and discussion...

Refactored Python Code
import sqlite3
connection = sqlite3.connect("c:\SQLite\Data\grading_system.db")
last_name = input("Enter a Last Name: ")
cursor = connection.execute("SELECT * FROM Students WHERE last_name = '" + last_name + "' ORDER BY last_name, first_name;")
print("-" * 50)
print("ID\t\tName\t\tClass\tGPA")
print("-" * 50)
for row in cursor:
    print(row[4] + "\t" + row[1] + " " + row[2] + "\t" + row[3] + "\t" + str(row[5]))
print("-" * 50)
connection.close()
Sample Run & Output
Enter a Last Name: Jones

--------------------------------------------------
ID              Name            Class      GPA
--------------------------------------------------
S28544679       Julia Jones     Freshman   4.00
S23001736       Pablo Jones     Sophomore  3.44
--------------------------------------------------
Notes

Practice

I recommend using the above code examples as a starting point and then practicing with the dynamic embedded SQL concepts by changing the query in different ways. You can use the DemoQueries.sql file to get some ideas to work with.









© 2023 John Gordon
Cascade Street Publishing, LLC