0

I have a system that is running php, and I recently needed to add connectivity to an MSSQL database. I have FreeTDS and UnixODBC installed/configured correctly, and I can make successful queries in python, and via utilities like tsql and isql. After looking at phpinfo() I've discovered I don't have a 'sqlsrv' section, and there is no mssql.so file in my php extensions directory.

I want to add this to my system without having to recompile/install php. Would I be able to find and download the mssql.so file, put it into my extensions directory, add extension=/path/to/mssql.so to my php.ini file, and reload apache to get this working? Or is there more steps I would need to take?

EDIT:

The system is running SLES11 with PHP 5.2

EDIT 2:

I've managed to get the php5-mssql extension installed. I grabbed the source, extracted it, and copies these files:

ext/mssql/config.m4
ext/mssql/php_mssql.c
ext/mssql/php_mssql.h

Then, in the directory where I copied the files to, I ran phpize (you will need to install php5-devel to get this tool), and compiled the extension like so:

./configure --with-mssql=/usr/local/freetds
make

I also had to add a line and comment out a line in php_mssql.c before it could actually compile correctly (not everyone will need to do this):

{NULL,NULL,NULL}
/*PHP_FE_END*/

This created the mssql.so file in /php_mssql/modules/ (relative to where I compiled the code), which I was able to move to my extensions directory (you can find this with php -i | grep extensions). I added extension=mssql.so to my php.ini file; however, there is still no 'sqlsrv section in phpinfo().

Some connection methods seem to partially work:

When running the following code from a shell, <h1>Connection Success</h1> is shown; but when opened in a browser, nothing after the mssql_connect line is shown:

<?php
//*************************************************************************
//Open Database Connection
//*************************************************************************
//phpinfo();
$dbserver="MyServer";
$dbusername="user";
$dbpassword="pass";
$defaultdb="DBName";
$cn = mssql_connect($dbserver,$dbusername,$dbpassword) or die("Connection Error");
$db = mssql_select_db($defaultdb,$cn) or die("Database Error");
echo "<h1>Connection Success</h1>";
?>

So it looks like I'm partially getting a connection that way? When I try with a PDO object, I get another error:

Code:

<?php
$con = new PDO('odbc:host=MyServer;dbname=DBName','user','pass');
?>

Error:

PHP Fatal error:  Uncaught exception 'PDOException' with message 'SQLSTATE[IM002] SQLDriverConnect: 0 [unixODBC][Driver Manager]Data source name not found, and no default driver specified' in /path/to/php/file/test3.php:3
Stack trace:
#0 /path/to/php/file/test3.php(3): PDO->__construct('odbc:host=MySer...', 'user', 'pass')
#1 {main}
  thrown in /path/to/php/file/test3.php on line 3

I've also tried the following (assuming that the PDO statement/DSN in the previous code was incorrrect):

<?php
try {
        $db = new PDO("odbc:Driver=FreeTDS; Server=MyServer; Port=1433; Database=DBName; UID=user; PWD=pass;");
} catch (PDOException $exception) {
        die("$exception");
}
echo "<h1>Success!</h1>";
?>

This showed <h1>Success!</h1> from the shell, but showed the following error in my web browser:

exception 'PDOException' with message 'SQLSTATE[08001] SQLDriverConnect: 0 [unixODBC][FreeTDS][SQL Server]Unable to connect to data source' in /path/to/php/file/test4.php:3 Stack trace: #0 /path/to/php/file/test4.php(3): PDO->__construct('odbc:Driver=Fre...') #1 {main}
EGr
  • 2,072
  • 10
  • 41
  • 61
  • What OS? Likely you need to install it from your package manager. – Mike Jul 24 '13 at 20:01
  • @Mike: SLES11; I only see packages for mysql, pgsql, and sqlite. – EGr Jul 24 '13 at 20:04
  • Ah, you're right. I notice now that Ubuntu also doesn't have a package for mssql. – Mike Jul 24 '13 at 20:07
  • @Mike I did find a package here: http://software.opensuse.org/package/php5-mssql?search_term=php5-mssql but I wasn't 100% certain if it would work correctly. – EGr Jul 24 '13 at 20:07
  • You can always just give it a try. If it's not going to work, you'll probably get some sort of error while trying to install. – Mike Jul 24 '13 at 20:08
  • @Mike It doesn't look like there is an easy way to grab that rpm from a shell. I'll let you know if I can get it, and get the extension working. – EGr Jul 24 '13 at 20:37
  • @Mike I was able to compile the extension from source, but now I'm having other issues (see Edit 2). – EGr Jul 24 '13 at 21:37
  • 2
    If it's working by command line but not through the web server, it must be a difference in your php.ini file for CLI and your web server. I'm not sure how SuSE does it, but with Debian-based servers, they are `/etc/php5/apache2/php.ini` and `/etc/php5/cli/php.ini` respectively. You can also see which ini file is loaded in `phpinfo()`. Also, make sure you check your error logs to see if it's putting anything in there when accessing by the browser since it doesn't output anything at all. – Mike Jul 24 '13 at 21:45
  • That worked! I didn't realize there were two php.ini files, and I was only editing the cli one. Thanks, I can connect with mssql_connect now! – EGr Jul 24 '13 at 21:52
  • Good to hear you got it working. – Mike Jul 24 '13 at 22:06

3 Answers3

1

In ODBC the error message contains elements in [] at the start of the message and the rightmost one is the part of the chain reporting the error (see ODBC Diagnostics & Error Status Codes. So, "[unixODBC][Driver Manager]Data source name not found, and no default driver specified" was reported by unixODBC. What unixODBC is saying is the string passed to the ODBC API SQLConnect or SQLDriverConnect does not identify a DSN (data source name) or an ODBC driver and there is no default DSN defined. You can find where your data sources are defined by running odbcinst -j e.g.,

$ odbcinst -j
unixODBC 2.2.14
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /home/martin/.odbc.ini
SQLULEN Size.......: 4
SQLLEN Size........: 4
SQLSETPOSIROW Size.: 2

Here, drivers are defined in /etc/odbcinst.ini, system data sources in /etc/odbc.ini and user data sources in /home/martin/.odbc.ini. As you'll probably be running PHP probably under a web server I'd stick to using the system data sources if I were you. You can list your system data sources with odbcinst -q -l -s. You find a a very good explanation of Linux/ODBC at Linux/UNIX ODBC.

Your second error "[unixODBC][FreeTDS][SQL Server]Unable to connect to data source" is reported by the SQL Server driver from FreeTDS so in this case you must have passed sufficient information to unixODBC to at least allow it to identify the driver, load it and call SQLConnect/SQLDriverConnect in it. You can see what was passed to unixODBC's SQLConnect/SQLDriverConnect by enabling tracing in unixODBC. You enable tracing of unixODBC by editing your odbcinst.ini file (locate with odbcinst -j command above) and adding the following to the top of it:

[ODBC]
Trace           = yes
TraceFile               = /tmp/unixodbc.log

Now, when you run your php example it will log to /tmp/unixodbc.log all ODBC API calls and the one you are looking for is SQLConnect or SQLDriverConnect. e.g., when I connect to a DSN called mydsn with a username and password of XXX and YYY I see:

[ODBC][31521][1374740062.012973][SQLDriverConnect.c][687]
                Entry:            
                        Connection = 0x9d7d430            
                        Window Hdl = (nil)            
                        Str In = [DSN=mydsn;UID=XXX;PWD=********][length = 29]            
                        Str Out = 0xbfdeb83c            
                        Str Out Max = 512            
                        Str Out Ptr = 0xbfdeb638            
                        Completion = 0
                UNICODE Using encoding ASCII 'ISO8859-1' and UNICODE 'UCS-2LE'

                DIAG [01000] [Easysoft][SQL Server Driver][SQL Server]Changed database context to 'master'.

                DIAG [01000] [Easysoft][SQL Server Driver][SQL Server]Changed language setting to us_english.

Note, this connection was successful and it clearly shows part of the connection string was DSN=mydsn and mydsn exists as a DSN in my /etc/odbcinst.ini.

isql can work differently to some ODBC enabled applications as isql calls the ODBC API SQLConnect whereas most ODBC applications these days are ODBC 3 aware and use SQLDriverConnect. The main difference is SQLConnect is only given 3 arguments, a DSN name, a username and a password where SQLDriverConnect is given a single string of attribute/value pairs defining the connection. I only tell you this so you are aware how it is possible for isql to work and something else not to.

However, in your second case when you examine your trace you'll see unixODBC got something useful enough to identify the driver, load it and call freeTDS's ODBC driver and the error "Unable to connect to data source" is coming from freeTDS. So, I suggest your DSN is probably ok and your freetds.conf is incorrect in some way. As I don't use freeTDS myself I'm not sure but I've heard you can use ODBC with freeTDS without any reference to the freetds.conf file and switches based on whether you use Server or ServerName. I'm sure there are loads of examples on the freeTDS web site.

bohica
  • 5,932
  • 3
  • 23
  • 28
  • I have an entry almost similar to that; except, i get the following lines after the `UNICODE` line: `DIAG [01000] [FreeTDS][SQL Server]Unexpected EOF from the server DIAG [01000] [FreeTDS][SQL Server]Adaptive Server connection failed DIAG [08001] [FreeTDS][SQL Server]Unable to connect to data source ` – EGr Jul 26 '13 at 21:39
  • You may be using the wrong TDS version (just a guess). Try enabling freeTDS logging and see what that says. You can always get more help on the freetds mailing listing - I don't see those guys on SO. – bohica Jul 27 '13 at 05:41
0

Here's how I connect to MS SQL servers from a LAMP (Ubuntu) stack:

/etc/odbc.ini

# Define a connection to a Microsoft SQL server
# The Description can be whatever we want it to be.
# The Driver value must match what we have defined in /etc/odbcinst.ini
# The Database name must be the name of the database this connection will connect to.
# The ServerName is the name we defined in /etc/freetds/freetds.conf
# The TDS_Version should match what we defined in /etc/freetds/freetds.conf
[mssql]
Description             = MSSQL Server
Driver                  = freetds
Database                = XXXXXX
ServerName              = MSSQL
TDS_Version             = 8.0

/etc/odbcinst.ini

# Define where to find the driver for the Free TDS connections.
[freetds]
Description     = MS SQL database access with Free TDS
Driver          = /usr/lib/i386-linux-gnu/odbc/libtdsodbc.so
Setup           = /usr/lib/i386-linux-gnu/odbc/libtdsS.so
UsageCount      = 1

/etc/freetds/freetds.conf

# The basics for defining a DSN (Data Source Name)
# [data_source_name]
#       host = <hostname or IP address>
#       port = <port number to connect to - probably 1433>
#       tds version = <TDS version to use - probably 8.0>

# Define a connection to the Microsoft SQL Server
[mssql]
        host = XXXXXX
        port = 1433
        tds version = 8.0

And here's the PHP code:

$con = new PDO('dblib:host=mssql;dbname=MyDB', 'domain\username', 'password');

You may need to tweak things a bit for your OS. To install the necessary software on Ubuntu I did something like this:

sudo apt-get install php5-odbc php5-sybase tdsodbc
Benny Hill
  • 6,191
  • 4
  • 39
  • 59
  • I have all of that set up, and can make connections with isql, tsql, and osql; but I'm getting an error when using the PDO object (see edit 2, above). It looks like it cannot find the DSN or something. Do you know what might be going on? – EGr Jul 24 '13 at 21:57
-1

Use PDO and instal this http://www.php.net/manual/en/ref.pdo-sqlsrv.php

I always use PDO it can easy do all the database interaction you need with different db drivers and the same php code. Except the query languages which is sometimes a little different.

For MSSQL you only need to add the drivers just paste the .dll's, add the entry to the conf.ini and restart apache.

botenvouwer
  • 4,334
  • 9
  • 46
  • 75
  • It looks like that only works on Windows systems. I assumed it was understood that I was using Linux (since I said I'm using UnixODBC), but I realize I should have included that in the post (see my edit). – EGr Jul 24 '13 at 20:34
  • Oh sorry then and good luck, btw why are you even using a microsoft sql server on a linux machine with all due respect isn't that asking for trouble. Just use a windows host for a microsoft sql server. While add it: Why not use a more suitable sql server for linux like mysql? – botenvouwer Jul 24 '13 at 20:41
  • The mssql system is already in place, and used by many different people in my organization. I'm trying to make another site that pulls some data from the DB for another purpose. I'm making a small site, and didn't want to use a Windows system for it (although it is proving to be somewhat challenging). – EGr Jul 24 '13 at 20:55