pyodbc - A Python DB API module for ODBC

About pyodbc

pyodbc is a Python module that allows you to access ODBC databases. It implements the Python Database API Specification v2.0.

Some notable features include:

Additional Features

The following features are beyond the requirements of the DB API. They are intended to provide a very Python-like, convenient programming experience, but you should not use them if your code needs to be portable between DB API modules. (Though we hope future DB API specifications will adopt some of these features.)

Access Values By Name

The DB API specifies that results must be tuple-like, so columns are normally accessed by indexing into the sequence (e.g. row[0]) and pyodbc supports this. However, columns can also be accessed by name:

  cursor.execute("select album_id, photo_id from photos where user_id=1")
  row = cursor.fetchone()
  print row.album_id, row.photo_id 
  print row[0], row[1] # same as above, but less readable

This makes the code easier to maintain when modifying SQL, more readable, and allows rows to be used where a custom class might otherwise be used. All rows from a single execute share the same dictionary of column names, so using Row objects to hold a large result set may also use less memory than creating a object for each row.

The SQL "as" keyword allows the name of a column in the result set to be specified. This is useful if a column name has spaces or if there is no name:

  cursor.execute("select count(*) as photo_count from photos where user_id=1")
  row = cursor.fetchone()
  print row.photo_count

Rows Values Can Be Replaced

Though SQL is very powerful, values sometimes need to be modified before they can be used. Rows allow their values to be replaced, which makes them even more convenient ad-hoc data structures.

  # Replace the 'start_date' datetime in each row with one that has a time zone.
  rows = cursor.fetchall()
  for row in rows:
    row.start_date = row.start_date.astimezone(tz)

Note that columns cannot be added to rows; only values for existing columns can be modified.

Cursors are Iterable

The DB API makes this an optional feature. Each iteration returns a row object.

  cursor.execute("select album_id, photo_id from photos where user_id=1")
  for row in cursor:
      print row.album_id, row.photo_id
  

Cursor.execute Returns the "Right" Thing

The DB API specification does not specify the return value of Cursor.execute, so pyodbc returns different types based on the SQL statement executed.

A select statement returns the cursor itself, allowing the execute results to be iterated over and used to fetch. This makes the code very compact:

  for row in cursor.execute("select album_id, photo_id from photos where user_id=1"):
      print row.album_id, row.photo_id

  row = cursor.execute("select count(*) from tmp").fetchone()
  
  rows = cursor.execute("select * from tmp").fetchall()

Update and delete statements return the number of rows affected:

  count = cursor.execute("update photos set processed=1 where user_id=1")

  count = cursor.execute("delete from photos where user_id=1")
  

All other SQL statements return None.

Connection.execute

pyodbc Connection objects have an execute method that creates new Cursors automatically.

    for row in cnxn.execute("select user_id from tmp"):
        print row.user_id

Since each call creates a new cursor, do not use this when executing multiple statements in a row.

Passing Parameters

As specified in the DB API, Cursor.execute accepts an optional sequence of parameters:

  cursor.execute("select a from tbl where b=? and c=?", (x, y))

However, pyodbc also accepts the parameters directly. Note that the parameters are not in a tuple:

  cursor.execute("select a from tbl where b=? and c=?", x, y)

Autocommit Mode

Connections can be put into autocommit mode using the autocommit keyword of the connect function or the autocommit attribute of the Connection object.

Miscellaneous ODBC Functions

Connection.getinfo function is an interface to SQLGetInfo.

Most of the ODBC catalog functions are available as methods on Cursor objects. The results are presented as SELECT results in rows that are fetched normally. Refer to Microsoft's ODBC documentation for details of how to use each function.

  cnxn   = pyodbc.connect(...)
  cursor = cnxn.cursor()
  for row in cursor.tables():
      print row.table_name
  
ODBC Function Method Description
SQLTables Cursor.tables Returns a list of table, catalog, or schema names, and table types.
SQLColumns Cursor.columns Returns a list of column names in specified tables.
SQLStatistics Cursor.statistics Returns a list of statistics about a single table and the indexes associated with the table.
SQLSpecialColumns Cursor.rowIdColumns Returns a list of columns that uniquely identify a row.
SQLSpecialColumns Cursor.rowVerColumns Returns a list of columns that are automatically updated any any value in the row is updated.
SQLPrimaryKeys Cursor.primaryKeys Returns a list of column names that make up the primary key for a table.
SQLForeignKeys Cursor.foreignKeys Returns a list of column names that are foreign keys in the specified table (columns in the specified table that refer to primary keys in other tables) or foreign keys in other tables that refer to the primary key in the specified table.
SQLProcedures Cursor.procedures Returns information about the procedures in the data source.
SQLProcedures Cursor.getTypeInfo Returns a information about the specified data type or all data types supported by the driver.

SourceForge.net Logo