Python 3

home

SQL Part 2: Working with Databases through Python

sqlite3 from Python: full example

The sqlite3 module provides programmatic access to sqlite3 databases.


Keep in mind that the interface you use for SQLite3 will be very similar to one that you would use for other databases such as mysql/MariaDB, so most of the code after the "connect()" call will be identical.


import sqlite3
conn = sqlite3.connect('example.db')  # a db connection object

# generate a cursor object
c = conn.cursor()                     # a cursor object for issuing queries


# execute change to database
c.execute("INSERT INTO test.dbo.revenue (company, state, cost) VALUES ('Acme, Inc.', 'CA', 23.9)")


# commit change
conn.commit()    # all changes to db must be committed


# select data from database
c.execute('SELECT * FROM test.dbo.revenue')


# cursor.description:  database columns
desc = c.description

for field in desc:
    fname = field[0]
    ftype = field[1]
    print(f'{fname}:  {ftype}')

      ### id:  <class 'int'>
      ### first_name:  <class 'str'>
      ### last_name:  <class 'str'>
      ### birthday:  <class 'datetime.date'>


# fetching options (customarily only one of these will be used)

# loop through results
for row in c:
    print(row)

# fetch one row
row = c.fetchone()
print(row)

# fetch several rows
rows = c.fetchmany(3)
print(rows)

# fetch all rows
rows = c.fetchall()
print(rows)


# close the connection
conn.close()




Connecting to database and generating a 'cursor' object

The connect string validates the user and specifies a host and database


Connecting to Database (and Disconnecting When Done)


The 'connect string' passed to connect() is the name of a database file. In other databases it would be a longer "connect string" that includes user and database information.

import sqlite3
conn = sqlite3.connect('example.db')  # a db connection object



# after completing database actions, close the connection promptly
# conn.close()

Generating a cursor object for issuing queries


A cursor object represents a request to the database. We will use the cursor object to execute queries and retrieve query results.

import sqlite3
conn = sqlite3.connect('example.db')  # a db connection object

c = conn.cursor()


# after completing database actions, close the connection promptly
# conn.close()




Selecting data from database; retrieving results

Four options for retrieving result rows: fetchone(), fetchmany(), fetchall() and 'for' looping


executing a select query

c.execute('SELECT * FROM revenue')

 
fetching options: depending on the size of the result set and how we'd like process the results, we have four options for retrieving results from the cursor object once a query has been executed.


looping through result set: similar to file looping

for row in c:
    print(row)       # returns a tuple row with each iteration



retrieving one row: most appropriate when only one row is expected

row = c.fetchone()  # returns a single tuple row



fetching several rows: allows processing results in batches

rows = c.fetchmany(3)  # returns a list of 3 tuple rows



fetching all rows: appropriate only if result set is not very large

rows = c.fetchall()   # returns a list of tuple rows



cursor.description: database columns information This attribute of the cursor object contains a tuple structure that describes each column: its name and type, as well as a number of internal attributes


desc = c.description

for field in desc:
    fname = field[0]
    ftype = field[1]
    print(f'{fname}:  {ftype}')

      ### id:  <class 'int'>
      ### first_name:  <class 'str'>
      ### last_name:  <class 'str'>
      ### birthday:  <class 'datetime.date'>




Inserting rows to database; committing changes

Any change to database must be committed to be made permanent.


c.execute("INSERT INTO revenue (company, state, cost) VALUES ('Acme, Inc.', 'CA', 23.9)")

conn.commit()


Inserting values into query dynamically SQL requires quotes around text values and no quotes around numeric values. This can cause confusion or issues, especially when our text values have quotes in them.


sqlite3 can be made to add the quotes for us, thus escaping any values as needed:

name = "Joe's Fashions"   # the single quote could be a problem when inserted into an SQL statement
state = 'NY'
value = 1.09

c.execute("INSERT INTO revenue (company, state, cost) VALUES (?, ?, ?)", (name, state, value))

conn.commit()



we can also insert multiple rows in one statement using this method:

insert_rows = [ ("Joe's Fashions", 'NY', 1.09), ('Beta Corp', 'CA', 1.39) ]

c.executemany("INSERT INTO test.dbo.revenue (company, state, cost) VALUES (?, ?, ?)", insert_rows)

conn.commit()




Deleting Rows

Delete some or all rows with this query (take care!)


DELETE FROM removes rows from a table.

DELETE FROM students WHERE student_id = 'jk43'

Take special care -- DELETE FROM with no critera will empty the table!

DELETE FROM students

WARNING -- the above statement clears out the table!





Identifying SQL-Specific Errors: sqlite3.OperationalError

This exception is generated by SQLite3, usually when our query syntax is incorrect.


When you receive this error, it means you have asked sqlite3 to do something it is unable to do. In these cases, you should print the query just before the execute() statement.


query = "INSERT INTO revenue (company, state) VALUES ('Acme', 'CA')"
c.execute(query)
conn.commit()

Traceback (most recent call last):
  File "", line 1, in 
sqlite3.OperationalError: table revenue has 3 columns but 2 values were supplied

A common issue is the use of single quotes inside a quoted value:

query = "INSERT INTO revenue (compnay, state, cost) VALUES ('Awful's', 'NJ', 20.39)"
c.execute(query)
conn.commit()    # all changes to db must be committed


Traceback (most recent call last):
  File "", line 1, in 
sqlite3.OperationalError: near "A": syntax error

Looking closely at the query above, you see that the name "Awful's" has a quote in it. So when SQL attempts to parse this string, it becomes confused by the quote in the text. The solution to this is to use parametarized arguments as described previously.





[pr]