Search code examples
ubuntuodbcpyodbcfreetdsunixodbc

Connect to MS SQL Server Database Using isql on Ubuntu


Ultimate goal: connect my Xubuntu 16.04 machine to a remote MS SQL Server 2017 database using pyodbc.

Intermediate goal: get isql to work; tsql works, but not isql.

I tried mirroring the settings on my Mac - see this question for what worked. Unfortunately, no joy. I have looked through many SO questions, such as: One, Two, and Three, and tried their approaches, none of which work. I'm confident that the Linux machine has the right ports open, because tsql works from my Xubuntu 16.04 machine. Unfortunately, I cannot get isql to work. I get the dreaded

[S1000][unixODBC][FreeTDS][SQL Server]Unable to connect to data source
[01000][unixODBC][FreeTDS][SQL Server]Adaptive Server connection failed
[ISQL]ERROR: Could not SQLConnect

errors. Also unfortunately, much of the documentation I've seen seems woefully out-of-date and contradictory. For example:

  1. In the odbc.ini file, should it be Server = stuff, 1433 or Server = stuff or ServerName = stuff with a separate port = line, or should I go with instance? There are too many options, and not enough documentation to figure this out.
  2. What exactly should go in the odbcinst.ini file? I don't have a libtdsS.so file in /usr/lib/x86_64-linux-gnu/odbc directory. Should I leave out the Setup line?
  3. What exactly should go in the freetds.conf file? Should I use the actual IP address?
  4. If I want to force FreeTDS to use a particular protocol version, how do I do that? Changing freetds.conf doesn't appear to affect the results of tsql -C. Or do I just need to log out and back in?
  5. Taking a step back: is there a better approach to the whole darn thing? I'm not interested in pymssql, as it appears to be abandonware at this point, in favor of pyodbc.
  6. I note that the tsql -LH stuff command produces no output. Is that command deprecated? Or how could I get the right settings from any command?
  7. Is there up-to-date, clear documentation available anywhere? Or an up-to-date, clear installation and usage guide anywhere, with trouble-shooting steps for the more common problems?

Many thanks for your time!

[EDIT] Here are the contents of a tracelog after enabling:

[ODBC][34479][1567549751.158470][__handles.c][460]
        Exit:[SQL_SUCCESS]
            Environment = 0x1913750
[ODBC][34479][1567549751.158517][SQLAllocHandle.c][377]
        Entry:
            Handle Type = 2
            Input Handle = 0x1913750
[ODBC][34479][1567549751.158532][SQLAllocHandle.c][493]
        Exit:[SQL_SUCCESS]
            Output Handle = 0x1914060
[ODBC][34479][1567549751.158551][SQLConnect.c][3721]
        Entry:
            Connection = 0x1914060
            Server Name = [ROEFDN806Q][length = 10 (SQL_NTS)]
            User Name = [mfad\m210028][length = 12 (SQL_NTS)]
            Authentication = [********][length = 8 (SQL_NTS)]
[ODBC][34479][1567549751.158987][SQLConnect.c][3929]Error: IM002
[ODBC][34479][1567549751.159017][SQLError.c][424]
        Entry:
            Connection = 0x1914060
            SQLState = 0x7ffd099daf10
            Native = 0x7ffd099daf0c
            Message Text = 0x7ffd099daf20
            Buffer Length = 500
            Text Len Ptr = 0x7ffd099daf0a
[ODBC][34479][1567549751.159034][SQLError.c][474]
        Exit:[SQL_SUCCESS]
            SQLState = IM002
            Native = 0x7ffd099daf0c -> 0
            Message Text = [[unixODBC][Driver Manager]Data source name not found and no default driver specified]
[ODBC][34479][1567549751.159066][SQLError.c][424]
        Entry:
            Connection = 0x1914060
            SQLState = 0x7ffd099daf10
            Native = 0x7ffd099daf0c
            Message Text = 0x7ffd099daf20
            Buffer Length = 500
            Text Len Ptr = 0x7ffd099daf0a
[ODBC][34479][1567549751.159079][SQLError.c][474]
        Exit:[SQL_NO_DATA]
[ODBC][34479][1567549751.159089][SQLError.c][424]
        Entry:
            Environment = 0x1913750
            SQLState = 0x7ffd099daf10
            Native = 0x7ffd099daf0c
            Message Text = 0x7ffd099daf20
            Buffer Length = 500
            Text Len Ptr = 0x7ffd099daf0a
[ODBC][34479][1567549751.159099][SQLError.c][474]
        Exit:[SQL_NO_DATA]
[ODBC][34479][1567549751.159130][SQLFreeHandle.c][290]
        Entry:
            Handle Type = 2
            Input Handle = 0x1914060
[ODBC][34479][1567549751.159144][SQLFreeHandle.c][339]
        Exit:[SQL_SUCCESS]
[ODBC][34479][1567549751.159156][SQLFreeHandle.c][220]
        Entry:
            Handle Type = 1
            Input Handle = 0x1913750

Here is my current odbc.ini file:

[ROEFDN806Q]
Description = "EOAM_RA Server"
Driver = FreeTDS
ServerName = ROEFDN806Q
Server = 10.146.186.7
Port = 1433
Database = EOAM_RA
UsageCount = 1
TDS_Version = 7.3

And here's my odbcinst.ini file:

[FreeTDS]
Description = "FreeTDS ODBC Driver"
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so

[ODBC]
Trace = yes
TraceFile = /tmp/odbctrace.txt

Solution

  • Microsoft's "ODBC Driver 17 for SQL Server" is the preferred driver for connecting to SQL Server. However, if you need to pass Windows credentials from a Linux box to a SQL Server instance then you do in fact need to use FreeTDS, at least for now.

    We get the required components via

    sudo apt install tdsodbc unixodbc
    

    Then we use sudo nano -w /etc/odbcinst.ini to create an entry like this:

    [FreeTDS]
    DESCRIPTION=FreeTDS ODBC driver
    DRIVER=/usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
    

    Next we use sudo nano -w /etc/odbc.ini to create an entry like this:

    [SQLServer01]
    DRIVER=FreeTDS
    SERVER=192.168.0.179
    PORT=49242
    DATABASE=myDb
    TDS_Version=7.2
    

    Finally, we can connect via isql (note the double backslash):

    isql SQLServer01 mydomain\\myusername mypassword