Thursday, December 13, 2012

Python sqlite3

Some notes on using sqlite3 from python. First, lets create a table in an in-memory database:
import sqlite3

DB_TABLE_NAME = 'cache'
DB_TABLE_COLUMN_DEFS = 'event blob'

conn = sqlite3.connect(':memory:')
cur = conn.cursor()

sql = 'CREATE TABLE %(table_name)s (%(column_defs)s)' % {
      'table_name': DB_TABLE_NAME,
      'column_defs': DB_TABLE_COLUMN_DEFS}

cur.execute(sql)
Next we want to insert multiple values at once. You can use executemany to avoid needing a ? for every single value, although the format it requires is quite clumsy. A list of values for insertion would look like this:
[('test',), ('test',), ('test',), ('test',), ('test',)]
Neither the questionmark or named parameter substitution seems to work for table names, so you'll need to stick those in using normal string interpolation. The actual insert statement is:
VALUES = [('test',)] * 58
sql = 'INSERT INTO %(table_name)s VALUES (?)' % {'table_name':
                                                  DB_TABLE_NAME}
cur.executemany(sql, VALUES)
This function will delete a list of ids by converting the list to the necessary array of tuples first:
def DeleteRows(id_list):
  """Deletes row from database.

  Args:
    id_list: list of row ids.
  """
  sql = 'DELETE FROM %s WHERE rowid IN (?)' % DB_TABLE_NAME

  # sqlite needs a sequence like [(34,), (38,)]
  id_tuples = []
  for rowid in id_list:
    id_tuples.append((rowid,))

  cur.executemany(sql, id_tuples)
Test code for this function looks like the following. Using executemany for select will get you an error, so I just spell out the necessary ?'s.
id_list = [8, 51, 52, 58]
select_list = [8, 51, 34, 38, 52, 58]
DeleteRows(id_list)
sql = 'SELECT rowid FROM %(table_name)s WHERE rowid IN (?,?,?,?,?,?)' % {
    'table_name': DB_TABLE_NAME}
result = cur.execute(sql, tuple(select_list))
assert(result.fetchall() == [(34,), (38,)])

No comments: