Frequently asked questions
Cannot connect to SQL Server
If your Python program/script can’t connect to a SQL Server instance, try the following:
By default SQL Server 2005 and newer don’t accept remote connections, you have to use SQL Server Surface Area Configuration and/or SQL Server Configuration Manager to enable specific protocols and network adapters; don’t forget to restart SQL Server after making these changes,
If SQL Server is on a remote machine, check whether connections are not blocked by any intermediate firewall device, firewall software, antivirus software, or other security facility,
Check that you can connect with another tool.
If you are using FreeTDS, then you can use the included
tsql
command to try to connect – it looks like this:$ tsql -H sqlserverhost -p 1433 -U user -P password -D tempdb locale is "en_US.UTF-8" locale charset is "UTF-8" using default charset "UTF-8" Setting tempdb as default database in login packet 1> SELECT @@VERSION 2> GO Microsoft SQL Server 2012 - 11.0.2100.60 (X64) Feb 10 2012 19:39:15 Copyright (c) Microsoft Corporation Developer Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) (1 row affected)
Note
Note that I use the
-H
option rather than the-S
option totsql
. This is because with-H
, it will bypass reading settings from thefreetds.conf
file likeport
andtds version
, and so this is more similar to what happens with pymssql.If you can’t connect with
tsql
or other tools, then the problem is probably not pymssql; you probably have a problem with your server configuration (see below), FreeTDS Configuration, network, etc.If you can connect with
tsql
, then you should be able to connect with pymssql with something like this:>>> import pymssql >>> conn = pymssql.connect( ... server="sqlserverhost", ... port=1433, ... user="user", ... password="password", ... database="tempdb") >>> conn <pymssql.Connection object at 0x10107a3f8> >>> cursor = conn.cursor() >>> cursor.execute("SELECT @@VERSION") >>> print(cursor.fetchone()[0]) Microsoft SQL Server 2012 - 11.0.2100.60 (X64) Feb 10 2012 19:39:15 Copyright (c) Microsoft Corporation Developer Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)
If something like the above doesn’t work, then you can try to diagnose by setting one or both of the following FreeTDS environment variables that control logging:
TDSDUMP
TDSDUMPCONFIG
Either or both of these can be set. They can be set to a filename or to
stdout
orstderr
.These will cause FreeTDS to output a ton of information about what it’s doing and you may very well spot that it’s not using the port that you expected or something similar. For example:
>>> import os >>> os.environ['TDSDUMP'] = 'stdout' >>> >>> import pymssql >>> conn = pymssql.connect(server="sqlserverhost") log.c:194:Starting log file for FreeTDS 0.92.dev.20140102 on 2014-01-09 14:05:32 with debug flags 0x4fff. config.c:731:Setting 'dump_file' to 'stdout' from $TDSDUMP. ... dblib.c:7934:20013: "Unknown host machine name" dblib.c:7955:"Unknown host machine name", client returns 2 (INT_CANCEL) util.c:347:tdserror: client library returned TDS_INT_CANCEL(2) util.c:370:tdserror: returning TDS_INT_CANCEL(2) login.c:418:IP address pointer is empty login.c:420:Server sqlserverhost:1433 not found! ...
Note
Note that pymssql will use a default port of 1433, despite any ports you may have specified in your
freetds.conf
file. So if you have SQL Server running on a port other than 1433, you must explicitly specify theport
in your call topymssql.connect
. You cannot rely on it to pick up the port in yourfreetds.conf
, even thoughtsql -S
might do this. This is why I recommend usingtsql -H
instead for diagnosing connection problems.It is also useful to know that
tsql -C
will output a lot of information about FreeTDS, that can be useful for diagnosing problems:$ tsql -C Compile-time settings (established with the "configure" script) Version: freetds v0.92.dev.20140102 freetds.conf directory: /usr/local/etc MS db-lib source compatibility: no Sybase binary compatibility: no Thread safety: yes iconv library: yes TDS version: 5.0 iODBC: yes unixodbc: no SSPI "trusted" logins: no Kerberos: no OpenSSL: no GnuTLS: no
If you use pymssql on Linux/Unix with FreeTDS, check that FreeTDS’s configuration is ok and that it can be found by pymssql. The easiest way is to test connection using
tsql
utility which can be found in FreeTDS package. See FreeTDS Configuration for more info,
Returned dates are not correct
If you use pymssql on Linux/*nix and you suspect that returned dates are not correct, please read the FreeTDS and dates page.
pymssql does not unserialize DATE
and TIME
columns to datetime.date
and datetime.time
instances
You may notice that pymssql will unserialize a DATETIME
column to a
datetime.datetime
instance, but it will unserialize DATE
and TIME
columns as simple strings. For example:
>>> cursor.execute("""
... CREATE TABLE dates_and_times (
... datetime DATETIME,
... date DATE,
... time TIME,
... )
... """)
>>> cursor.execute("INSERT INTO dates_and_times VALUES (GETDATE(), '20140109', '6:17')")
>>> cursor.execute("SELECT * FROM dates_and_times")
>>> cursor.fetchall()
[{u'date': u'2014-01-09', u'time': u'06:17:00.0000000',
u'datetime': datetime.datetime(2014, 1, 9, 12, 41, 59, 403000)}]
>>> cursor.execute("DROP TABLE dates_and_times")
Yep, so the problem here is that DATETIME
has been supported by FreeTDS for a long time, but DATE
and TIME
are
newer types in SQL Server, Microsoft never added support for them to db-lib
and FreeTDS added support for them in version 0.95.
If you need support for these data types (i.e. they get returned from the
database as their native corresponding Python data types instead of as strings)
as well as for the DATETIME2
one, then make sure the following conditions
are met:
You are connecting to SQL Server 2008 or newer.
You are using FreeTDS 0.95 or newer.
You are using TDS protocol version 7.3 or newer.
“DB-Lib error message 20004, severity 9: Read from SQL server failed” error appears
On Linux/*nix you may encounter the following behaviour:
>>> from pymssql import _mssql
>>> c=_mssql.connect('hostname:portnumber','user','pass')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
_mssql.DatabaseException: DB-Lib error message 20004, severity 9:
Read from SQL server failed.
DB-Lib error message 20014, severity 9:
Login incorrect.
It may happen when one of the following is true:
freetds.conf
file cannot be found,tds version
infreetds.conf
file is not7.0
or4.2
,any character set is specified in
freetds.conf
,an unrecognized character set is passed to
_mssql.connect()
orpymssql.connect()
method.
"Login incorrect"
following this error is spurious, real "Login
incorrect"
messages has code=18456 and severity=14.
Unable to use long username and password
This is a solved FreeTDS problem but you need to be using FreeTDS 0.95 or newer, if you are stuck with 0.91 then keep in mind this limitation, even when you can get usernames, passwords longer than 30 to work on tsql.
Error in stored procedure does not throw Python exception
Consider the stored procedure:
CREATE PROCEDURE my_sp
AS
BEGIN
SET NOCOUNT ON;
SELECT 1;
SELECT 1/0;
END
If we run that in SSMS with EXEC my_sp
we see the following in the Messages tab:
Msg 8134, Level 16, State 1, Procedure my_sp, Line 6 [Batch Start Line 0]
Divide by zero error encountered.
However, if we do the same thing in Python we don’t get an exception:
>>> import pymssql
>>> cnxn = pymssql.connect("192.168.0.199", "scott", "tiger^5HHH", "test")
>>> crsr = cnxn.cursor()
>>> crsr.execute("EXEC my_sp")
>>>
That’s because when a stored procedure (or anonymous code block) returns multiple result sets, the first result set (from SELECT 1) is automatically made available for us to process, e.g., by using crsr.fetchall()
:
>>> crsr.fetchall()
[(1,)]
>>>
but the second result set is queued until we call crsr.nextset()
. If that result contains an error code then a pymssql exception is thrown:
>>> crsr.nextset()
Traceback (most recent call last):
File "src\\pymssql\\_pymssql.pyx", line 494, in pymssql._pymssql.Cursor.nextset
File "src\\pymssql\\_mssql.pyx", line 1461, in pymssql._mssql.MSSQLConnection.nextresult
File "src\\pymssql\\_mssql.pyx", line 1343, in pymssql._mssql.MSSQLConnection.get_result
File "src\\pymssql\\_mssql.pyx", line 1817, in pymssql._mssql.check_cancel_and_raise
File "src\\pymssql\\_mssql.pyx", line 1844, in pymssql._mssql.maybe_raise_MSSQLDatabaseException
File "src\\pymssql\\_mssql.pyx", line 1861, in pymssql._mssql.raise_MSSQLDatabaseException
pymssql._mssql.MSSQLDatabaseException: (8134, b'Divide by zero error encountered.DB-Lib error message 20018, severity 16:\nGeneral SQL Server error: Check messages from the SQL Server\n')
So, if your stored procedure is going to return multiple result sets you need to make sure that you call .nextset()
enough times to process them all.
More troubleshooting
If the above hasn’t covered the problem you can send a message describing it to the pymssql mailing list. You can also consult FreeTDS troubleshooting page for issues related to the TDS protocol.