========================== 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 (Build 7601: Service Pack 1) (1 row affected) .. note:: Note that I use the ``-H`` option rather than the ``-S`` option to ``tsql``. This is because with ``-H``, it will bypass reading settings from the ``freetds.conf`` file like ``port`` and ``tds 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), :doc:`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 >>> 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 (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`` or ``stderr``. 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 the ``port`` in your call to ``pymssql.connect``. You cannot rely on it to pick up the port in your ``freetds.conf``, even though ``tsql -S`` might do this. This is why I recommend using ``tsql -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 :doc:`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 :doc:`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 :class:`python: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. Shared object "libsybdb.so.3" not found ======================================= On Linux/\*nix you may encounter the following behaviour:: >>> from pymssql import _mssql Traceback (most recent call last): File "", line 1, in ? ImportError: Shared object "libsybdb.so.3" not found It may mean that the FreeTDS library is unavailable, or that the dynamic linker is unable to find it. Check that it is installed and that the path to ``libsybdb.so`` is in ``/etc/ld.so.conf`` file. Then do ``ldconfig`` as root to refresh linker database. On Solaris, I just set the ``LD_LIBRARY_PATH`` environment variable to the directory with the library just before launching Python. pymssql 2.x bundles the FreeTDS ``sybdb`` library for supported platforms. This error may show up in 2.x versions if you are trying to build with your own FreeTDS. "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 "", line 1, in _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`` in ``freetds.conf`` file is not ``7.0`` or ``4.2``, * any character set is specified in ``freetds.conf``, * an unrecognized character set is passed to :func:`_mssql.connect()` or :func:`pymssql.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`_. .. _page for issues related to the TDS protocol: https://www.freetds.org/userguide/troubleshooting.html