How-to: ODBC connection to DB2 instance (e.g. Mitel CSM)

ibm-db2I’m sure this is a very niche article. Which means if you’ve arrived here, you’ve almost certainly been as frustrated as I have with the documentation for DB2 ODBC connections.

Background: I’m trying to connect to a DB2 instance, running on a Windows machine. I imagine that this procedure will work just as well for instances running on other architectures. And I’m trying to connect from another Windows machine, to pass data into a Microsoft SQL-powered data warehouse.

You will need the “IBM Data Server Driver for ODBC and CLI (Windows/x86-32 32 bit) V10.5 Fix Pack 8“. If the link doesn’t work any more, go to IBM Fix Central and search for “Windows Data Server Driver ODBC 10.5”. Possibly other versions will work, but this is the one I found most reliable.

The process is as follows:

  1. Copy the entire extracted folder to the root of a data drive (e.g. to D:\DB2, E:\DB2 as the case may be).
  2. Add the bin folder to the computer’s PATH environment variable (DB2\clidriver\bin).
    db2_odbc_01
  3. Launch an elevated command prompt.
  4. Navigate to the DB2 bin folder. E.g.:
    e:
    cd e:\DB2\clidriver\bin
  5. Install the ODBC driver:
    db2oreg1.exe -i
  6. On Windows Server 2012 R2, also run:
    db2oreg1 -setup
  7. The driver will now appear in the 32-bit ODBC driver list:
    db2_odbc_02

To connect:

  1. Launch the 32-bit ODBC data source administration applet.
  2. On the User DSN or System DSN tab, click Add.
    db2_odbc_03
  3. Select the ODBC driver and click Finish.
    db2_odbc_04
  4. Name the data source (e.g. “CSM”, in my case) and then click “Add”, next to the Database alias dropdown.
    db2_odbc_05
  5. Enter User ID and password.
    db2_odbc_06
  6. Check the “Save password” box. Note the warning and click OK.
    db2_odbc_07
  7. Switch to the Advanced Settings tab.
    db2_odbc_08
  8. Use the “Add” button, to enter the following values.
    Hostname: [host DNS name or IP address]
    Port:     50000
    Protocol: TCP/IP
    Database: [DB name, e.g. CTI_DATA]
  9. Review the settings and click OK:
    db2_odbc_09
  10. To test the connection, first click the “Configure” button.
    db2_odbc_12
  11. The credentials are stored in the ini file, so you do not need to enter them here. Simply click “Connect”.
    db2_odbc_10
  12. You should see a success message.
    db2_odbc_11

If you’re looking for a free, Windows-based ODBC interrogation program, there are a few out there. All the ones I tried had quirks in their interfaces. I’ve had most success with ODBC query tool though. Here it is, running under Windows 10:

odbc-query-tool

If that doesn’t work for you, you can try the almost identically named ODBC QueryTool.

Connecting to Windows/MSSQL 2008 from Linux/CodeIgniter/PHP

Update: I’ve written a new article, covering CodeIgniter 3 and Ubuntu 14/16. Read it here.

Microsoft SQL Connecting to Microsoft SQL Express 2008 from Linux/PHP is a lot trickier than I expected. These notes are really for my own benefit so I can reproduce the setup, but maybe they’ll help you too. One of the problems is that many existing PHP drivers for MS SQL have difficulty talking to SQL 2008. Here’s a workaround using FreeTDS and ODBC.

My web application is built using CodeIgniter, the PHP application framework. It resides on an Ubuntu Server box, running Apache. Prerequisites on that Ubuntu Server (which I installed using Aptitude, but your favourite package manager will do):

  • unixODBC
  • FreeTDS
  • FreeTDS development package/(header files and libraries)

To my freetds.conf file (in /etc/freetds on my server) I added a section that looks something like this:

[my-server]
host = my.server.local
port = 1433
tds version = 9.0

Note: TDS version 9.0 should work with SQL 2008.

In /etc/odbcinst.ini, add the following ODBC driver (32-bit):

[TDS]
Driver = /usr/lib/odbc/libtdsodbc.so
Description = FreeTDS driver
Setup = /usr/lib/odbc/libtdsS.so

or 64-bit:

[TDS]
Driver = /usr/lib64/libtdsodbc.so
Description = FreeTDS driver
Setup = /usr/lib64/libtdsS.so

(You may need to check the precise location of the driver and setup files.)

And to /etc/odbc.ini, I inserted a DSN similar to the following:

[my-server]
Driver = TDS
Description = My Server
ServerName = my-server
Database = my-db

Generally within CodeIgniter, I am connecting to MySQL databases and that’s how my default connection is configured. I therefore added a second configuration to my database.php configuration file, like this:

$db['my_server']['hostname'] = "dsn=my-server;uid=myusername;pwd=mypassword";
$db['my_server']['username'] = '';
$db['my_server']['password'] = '';
$db['my_server']['database'] = '';
$db['my_server']['dbdriver'] = 'odbc';
$db['my_server']['dbprefix'] = '';
$db['my_server']['pconnect'] = TRUE;
$db['my_server']['db_debug'] = TRUE;
$db['my_server']['cache_on'] = FALSE;
$db['my_server']['cachedir'] = '';
$db['my_server']['char_set'] = 'utf8';
$db['my_server']['dbcollat'] = 'utf8_general_ci';

Now the ODBC driver within CodeIgniter can produce queries that MS SQL doesn’t like. We can fix this with a hack. You really REALLY shouldn’t do it this way (!) but to get things working and as described >here<, I edited the CodeIgniter core file system/database/drivers/odbc_driver.php. The function _from_tables() has a line reading:

return '('.implode(', ', $tables).')';

I changed it to this:

return implode(', ', $tables);

(In other words, we’re removing the spurious parentheses.)

I created a database method m_my_server.php like this:

/**
 * NOTE: We're using a feature-incomplete driver here.  Don't attempt to use
 * CodeIgniter's ActiveRecord Class or num_rows().  Use bare queries instead.
 */
class M_my_server extends Model {

  var $my_server;

  function M_my_server() {
      parent::Model();
      $this->my_server = $this->load->database('my_server', TRUE);
  }

  function get() {
    $query = $this->my_server->query('SELECT TOP(100) * FROM dbo.tblUserSummary');
    $result = $query->result_array();  // note ->num_rows() doesn't work with this driver
    if(count($result) > 0) {
      return $result;
    } else {
      return false;
    }

  }
}

/* End of file m_my_server.php */
/* Location: ./application/models/m_my_server.php */

At the SQL Server end, I set up a new standard SQL user (myusername/mypassword) rather than attempting to get Windows authentication to work (I bet it wouldn’t).

My SQL instance wasn’t listening to TCP/IP connections by default. I fired up SQL Server Configuration Manager and browsed to SQL Server Network Configuration –> Protocols for [my db instance]. Then you have to right-click TCP/IP and click Enable.

With all that in place, the following controller produces successful results:

  function SQLtest() {
    $this->load->model('m_my_server');
    $result = $this->m_my_server->get();
    if($result) {
      print_r($result);
    } else {
      echo 'nada';
    }
    exit;
  }

It’s not ideal; for one thing, bare SQL queries involve learning Microsoft’s particular dialect of SQL (whereas I’m used to MySQL). The tables I’m querying are generated by Microsoft Forefront TMG though, so I’m basically stuck with MSSQL. At least now I can query those tables from my favourite PHP application framework.

Image copyright © Microsoft. Used with permission from Microsoft.