Getting Help and Reporting Issues
If you are having trouble, first make sure you are using a recent version. In particular, use the 3.x version from the master branch. I'd really like to stop support the 2.1.x versions, but I will until there are very few people using them.
Be sure to search the issues (including closed ones) and the discussion group.
If you have questions, start by posting something to the discussion group, which allows others to help find the problem.
If you are sure you have a bug, try to create a small test to reproduce the problem and open a new issue.
Error Messages
Connecting fails with an error about SQL_ATTR_AUTOCOMMIT
pyodbc.Error:('HYC00','[HYC00][Microsoft][ODBC Excel Driver]Optional feature not implemented (106) (SQLSetConnectAttr(SQL_ATTR_AUTOCOMMIT))')
Add autocommit=True
to the connection call.
ODBC drivers always start with autocommit turned on, but the Python DB API specification requires it to be turned off. After a connection is made, pyodbc first attempts to turn off autocommit before returning the connection. If the driver does not support transactions, such as the Microsoft Excel driver, you will see an error like the following:
If you set the autocommit keyword to True, pyodbc will not attempt any changes to the connection since it will already have autocommit turned on:
cnxn = pyodbc.connect('DSN=test', autocommit=True)
Connecting fails on OS/X 10.4 with an error about SQL_ATTR_CONNECTION_POOLING
Apparently unixODBC on OS/X 10.4 does not support connection pooling, so you will see an error like:
Fatal Python error: Unable to set SQL_ATTR_CONNECTION_POOLING attribute.
Abort trap
You will need to set pyodbc.pooling to False before your first connection is made:
pyodbc.pooling = False
Connection pooling works on 10.5 and above.
Catalog procedure 'xxx' can not be run in a transaction
This error was reported by Sybase ASE 15 with FreeTDS when running Cursor.primaryKeys(), but I would expect similar errors when using the other catalog functions.
For some reason, ASE does not allow the stored procedure "sp_keys" to be run inside of a transaction. By default all pyodbc connections start with a transaction, so autocommit will need to be turned on. It can be turned on using the autocommit
keyword to the connect function, or it can be turned on temporarily like this:
cnxn.autocommit = true
rows = cursor.primaryKeys().fetchall()
cnxn.autocommit = false
Data Questions
How do I retrieve autogenerated/identity values?
Unfortunately ODBC does not have a way to retrieve the value of autogenerated values.
(There is a function that looks like it was designed for this, but a closer read of the documentation explains it shouldn't be used.)
Many databases do provide a way to access this using a 2nd select however.
SQL Server
Use "SELECT @@IDENTITY".
Note that @@IDENTITY returns the last generated value, so if a trigger causes a 2nd insert, you'll get the trigger's generated value.
SQL Server also provides SCOPE_IDENTITY() which is supposed to fix this. Unfortunately the SQL Server ODBC driver calls an internal stored procedure for each execute call which messes up the scoping, making this unusable.
DB/2
Use the following:
value = cursor.execute("select IDENTITY_VAL_LOCAL() from SYSIBM.SYSDUMMY1").fetchone()[0]
Note that value
is always going to be a Decimal object. The IBM documentation for IDENTITY_VAL_LOCAL() says
The result is a DECIMAL(31,0), regardless of the actual data type of the corresponding identity column.
You can use a cast to change the datatype if necessary:
select cast(IDENTITY_VAL_LOCAL() as integer) from SYSIBM.SYSDUMMY1
Why are inserts, updates, and deletes silently failing?
Did you forget to call Connection.commit()?
People used to ODBC but new to the Python DB API often expect connections to start in autocommit mode. Since the Python DB API requires manual commit, pyodbc connections do not autocommit by default. You must call cnxn.commit() after your inserts and deletes.
This is usually the best design for complex database work since you can batch multiple statements and commit them in one transaction. Partial work is automatically rolled back when an exception is raised because the connection object is closed when deleted.
However, if you really want autocommit, set the connection function's autocommit keyword parameter to true:
cnxn = pyodbc.connect(cstring, autocommit=True)
or use the Connection object's autocommit attribute:
```
Check the current setting
print 'turned on? ', cnxn.autocommit
Turn autocommit on
cnxn.autocommit = True ```
Excel sometimes returns NULL even though there is data
Since Excel spreadsheets don't really have data types, the Excel driver uses the first 8 rows to determine what data type to assign to each. The majority type in the first 8 rows determines the type.
For example, if a table in Excel looks like this:
| id | value | |:---|:------| | 1 | a | | 2 | a | | 3 | a | | 4 | a | | hi | a |
The column id will be assigned data type 'float' since most of the values are numbers.
When a value is read that doesn't match the data type, such as 'hi' in the 5th row, Excel cannot convert it and will return NULL.
Unicode or Garbage from MySQL
If your database columns have Unicode, you may need to add CHARSET=UTF8 to your connection string.
Also note that metadata, such as results from Cursor.columns, is in Unicode, so even if your tables only use ASCII, you might need this setting.
Serializing to JSON
To serialize each row as a JSON object, convert each one to a dictionary mapping column name to value like so:
obj = { t[0]: value for (t, value) in zip(row.cursor_description, row) }
The cursor_description variable is simply the Cursor.description list. The first item (0) of each element is the column's name.
Obviously you'll need to ensure the column names are good Javascript names and the data types are understood by the json module.
Miscellaneous Questions
How can I set the application name in SQL Server?
In SQL Server, each connection has an application name which can be very helpful for troubleshooting. This is set using the APP keyword in your connection string, like so:
cnxn = pyodbc.connect('dsn=test;pwd=pwd;APP=MyApp')
In this example, the connection would show up as MyApp.
Building Questions
Doesn't build on Linux
On Linux, pyodbc is usually built with unixODBC, so it will need the unixODBC header files installed.
On a RedHat/Fedora/CentOS box, this RPM is usually named unixODBC-devel
yum install unixODBC-devel
Notes And Research
Mac OS/X
ODBC was not included until Jaguar. The libraries included are actually OpenLink Software's iODBC library. (Reference: Open Database Connectivity in Jaguar)