上一篇讲了如何安装unixODBC+ODBC Driver 11 for SQL Server,安装完毕以后,我发现其实使用DSN方式根本就不能连接到数据库.在配置了DSN
sudo vim /etc/odbc.ini
[mhdsn]
Driver = /opt/microsoft/msodbcsql/lib64/libmsodbcsql-11.0.so.2270.0
Description = Microsoft ODBC Driver 11 for SQL Server
Trace = Yes
Server = 111.111.111.111
Port = 1433
Database = mhdb
Socket=tcp
而另一个配置则为
~ cat /etc/odbcinst.ini
[ODBC Driver 11 for SQL Server]
Description=Microsoft ODBC Driver 11 for SQL Server
Driver=/opt/microsoft/msodbcsql/lib64/libmsodbcsql-11.0.so.2270.0
Threading=1
UsageCount=1
[ODBC]
Trace = Yes
TraceFile = /tmp/odbc.log
在这情况下,我使用微软的sqlcmd连接服务器,是失败的,原因不知道,情况如下:
➜ ~ sqlcmd -S mhdsn
Sqlcmd: Error: Microsoft ODBC Driver 11 for SQL Server : Login timeout expired.
Sqlcmd: Error: Microsoft ODBC Driver 11 for SQL Server : A network-related or instance-specific error has occurred while establishing a connection to SQL Server. Server is not found or not accessible. Check if instance name is correct and if SQL Server is configured to allow remote connections. For more information see SQL Server Books Online..
Sqlcmd: Error: Microsoft ODBC Driver 11 for SQL Server : TCP Provider: Error code 0x2AF9.
但是我发现使用sqlcmd指定服务器连接却是成功的
sqlcmd -U sa -S 111.111.111.111,1433
使用的测试代码,基本上微软的代码,简单修改了一点儿.代码如下:
#include
#include
#include
#include
#include
#define NAME_LEN 50
#define PHONE_LEN 20
void show_error()
{
printf ( "error\n" );
}
int main()
{
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt = 0;
SQLRETURN retcode;
SQLCHAR szName[NAME_LEN], szPhone[PHONE_LEN], sCustID[NAME_LEN];
SQLLEN cbName = 0, cbCustID = 0, cbPhone = 0;
// Allocate environment handle
retcode = SQLAllocHandle ( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv );
// Set the ODBC version environment attribute
if ( retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO )
{
retcode = SQLSetEnvAttr ( henv, SQL_ATTR_ODBC_VERSION, ( SQLPOINTER* ) SQL_OV_ODBC3, 0 );
// Allocate connection handle
if ( retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO )
{
retcode = SQLAllocHandle ( SQL_HANDLE_DBC, henv, &hdbc );
// Set login timeout to 5 seconds
if ( retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO )
{
SQLSetConnectAttr ( hdbc, SQL_LOGIN_TIMEOUT, ( SQLPOINTER ) 5, 0 );
// Connect to data source
// retcode = SQLConnect ( hdbc, ( SQLCHAR* ) "SQLCMD", SQL_NTS, ( SQLCHAR* ) "Test1", 5, ( SQLCHAR* ) "Password1", 9 );
SQLCHAR OutConnStr[2048]= {0};
SQLSMALLINT OutConnStrLen;
SQLCHAR InConnectionString[] = {"DRIVER={ODBC Driver 11 for SQL Server};"
"SERVER={111.111.111.111,1433};UID={sa};PWD={xxxxxxxx};"};
retcode = SQLDriverConnect ( hdbc,NULL, ( SQLCHAR* ) InConnectionString,sizeof ( InConnectionString ),
OutConnStr, sizeof ( OutConnStr ),&OutConnStrLen,SQL_DRIVER_NOPROMPT );
// Allocate statement handle
if ( retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO )
{
retcode = SQLAllocHandle ( SQL_HANDLE_STMT, hdbc, &hstmt );
retcode = SQLExecDirect ( hstmt, ( SQLCHAR * ) "SELECT CustomerID, ContactName, Phone FROM CUSTOMERS ORDER BY 2, 1, 3", SQL_NTS );
if ( retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO )
{
// Bind columns 1, 2, and 3
retcode = SQLBindCol ( hstmt, 1, SQL_C_CHAR, sCustID, 100, &cbCustID );
retcode = SQLBindCol ( hstmt, 2, SQL_C_CHAR, szName, NAME_LEN, &cbName );
retcode = SQLBindCol ( hstmt, 3, SQL_C_CHAR, szPhone, PHONE_LEN, &cbPhone );
// Fetch and print each row of data. On an error, display a message and exit.
for ( int i=0 ; ; i++ )
{
retcode = SQLFetch ( hstmt );
if ( retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO )
show_error();
if ( retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO )
printf ( "%d: %s %s %s\n", i + 1, sCustID, szName, szPhone );
else
break;
}
}
// Process data
if ( retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO )
{
SQLCancel ( hstmt );
SQLFreeHandle ( SQL_HANDLE_STMT, hstmt );
}
SQLDisconnect ( hdbc );
}
else
{
printf ( "retcode=%d, DriverConnect Failed.\n", retcode );
SQLCHAR sqlstate[255];
SQLINTEGER nativeErrorPtr;
retcode = SQLGetDiagRec ( SQL_HANDLE_DBC, hdbc, 1, sqlstate, &nativeErrorPtr, OutConnStr, 255, &OutConnStrLen );
printf ( "SQLDriverConnect failed with ret=%d, errText=%s.\n", retcode, OutConnStr );
}
SQLFreeHandle ( SQL_HANDLE_DBC, hdbc );
}
}
SQLFreeHandle ( SQL_HANDLE_ENV, henv );
}
}
以上代码在我的机器上可以工作,ubtuntu14.04,我花了点功夫在SQLDriverConnect在连接字符串上,而且我是从上面的trace log中看到的连接方法,就拿过来修改了.因为我在odbcinst.ini上面添加了Trace = Yes TraceFile = /tmp/odbc.log 所在查看/tmp/odbc.log,可以看出来使用sqlcmd失败的时候,具体原因是什么.有时候猛一看挺乱的,不知道错在什么地方,但认真看下去,会发现,我晕,原来它一直都是在调用odbc的API啊,到SQLDriverConnect挂了.看一看SQLDriverConnect它的连接参数,发现原来是这样拼的啊.所以经验挺重要的,没失败过,就要多花一点时间在上面搞了.