unixODBC是用于非Windows平台下的开放式数据库连接工具,可从官网下载:http://www.unixodbc.org/ 。unixODBC提供了对ODBC的支持,但它只是一个ODBC管理器,要连接实际的数据库还得提供对应数据库的ODBC驱动。
下载之后根据以下步骤安装:
tar -xvf unixODBC-2.3.7.tar.gz
cd unixODBC-2.3.7
./configure --prefix=/usr/local/unixODBC #--prefix选项用于指定安装目录,不指定的话默认安装在/usr/local
make
sudo make install
使用以下命令测试unixODBC是否安装成功
odbcinst -j
如果成功显示以下信息说明安装完成
unixODBC 2.3.7
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /home/robot/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8
FreeTDS是一组用于在unix和Linux下访问SqlServer和Sybase的程序库,提供ODBC驱动,可从官网下载: http://www.freetds.org/software.html 。(也可以直接安装微软提供的ODBC驱动程序:https://docs.microsoft.com/zh-cn/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server?view=sql-server-2017 )
下载之后根据以下步骤安装:
tar -xvf freetds-patched.tar.gz
cd freetds-1.00.111
./configure --prefix=/usr/local/freetds --with-tdsver=7.0 --enable-msdblib #--with-tdsver选项用于指定TDS协议的版本,--enable-msdblib选项表示启用微软数据库函数库
make
sudo make install
安装完成后可以使用以下命令查看安装信息
tsql -C
如果出现以下信息说明安装完成
Version: freetds v1.00.111
freetds.conf directory: /usr/local/etc
MS db-lib source conpatibility: yes
Sybase binary compatibility: no
Thread safety: yes
iconv library: yes
TDS version: 7.0
iODBC: no
unixobc: yes
SSPI "tursted" logins: no
Kerberos: no
OpenSSL: yes
GnuTLS: no
MARS: no
也可以使用tsql命令在终端中连接数据库
tsql -H 127.0.0.1 -p 1433 -U sa -P Robot123456
其中,-H 表示主机ip地址, -p 表示端口号,-U 表示用户名,-P 表示密码。如果出现以下信息表示连接成功
locale is "zh_CN.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
1>
至此,我们的准备工作已经完成,可以通过freetds提供的接口连接SQLServer数据库了。使用freetds时需要包含的头文件为sybdb.h、sybfront.h,需要连接的动态链接库为sybdb。
接下来介绍一下常用的函数,在此之前不得不先介绍几个变量:
<1>RETCODE:我们在头文件sybdb.h头文件中发现了他的先关定义, 其实RETCODE就是int, 原始代码是:typedef int RETCODE
<2>SUCCEED:这个值也是int, 他的定义也位于sybdb.h上, 原始代码为:#define SUCCEED 1
<3>FAIL:这个值也是int, 他的定义也位于sybdb.h上, 原始代码为:#define FAIL 0
初始化函数dbinit()
函数原型为 RETCODE dbinit(void);
返回值 RETCODE:<1>成功时返回SUCCEED <2>失败时返回FAIL
登录信息结构体生成函数dblogin()
函数原型为 LOGINREC* dblogin(void);
返回值 <1>失败时返回NULL
<2>成功时返回一个LOGINREC指针, 这是一个结构体, 这个结构体中包含了连接数据库的相关参数
LOGINREC 结构体中的内容:
char* client_charset 客户端字符编码集
char* client_hostname 连接数据库的IP
char* username 连接数据库的用户名称
char* password 连接数据库时使用的密码
int query_timeout 发送请求命令时的超时时间
int connect_timeout 连接数据库的超时时间
登录信息相关选项的值设置函数dbsetlname()
函数原型 RETCODE dbsetlname(LOGINREC* login, const char* value, int which);
返回值 <1>成功时返回SUCCEED <2>失败时返回FAIL
参数 <1> LOGINREC*:一个LOGINREC指针
<2> value:我们要设置的选项的值
<3> which:我们要设置的选项
登录用户名设置函数DBSETLUSER()
函数原型 DBSETLUSER(LOGINREC* login, char* UserName);
返回值 RETCODE:<1>函数执行成功时返回SUCCEED <2>函数执行失败时返回FAIL
参数 <1>LOGINREC*:一个LOGINREC指针
<2>UserName:登录数据库的用户名
登录密码设置函数DBSETLPWD()
函数原型 DBSETLPWD(LOGINREC* login, char* PassWord);
返回值 RETCODE:<1>函数执行成功时返回SUCCEED <2>函数执行失败时返回FAIL
参数 <1>LOGINREC*:一个LOGINREC指针
<2>PassWord:登录数据库的用户的密码
数据库管理系统连接函数dbopen()
函数原型 DBPROCESS* dbopen(LOGINREC* login, const char* server);
返回值 <1>成功时返回DBPROCESS*, 一个成功连接到数据库的句柄
<2>失败时返回NULL
参数 <1>LOGINREC*:一个LOGINREC指针, 指针中一定要保存了连接使用户的用户名称, 以及用户的密码
<2>server:要连接数据库的IP地址
包含一系列数据表的具体数据库连接函数dbuse()
函数原型 RETCODE dbuse(DBPROCESS* dbproc, const char* name);
返回值 <1>成功时返回SUCCEED <2>失败时返回FAIL
参数 <1>dbproc:已经连接到数据库的连接句柄
<2>name:要使用的数据库的名字
SQL命令提交函数dbcmd()
函数原型 RETCODE dbcmd(DBPROCESS* dbproc, const char cmdstrmg[]);
返回值 <1>执行成功时返回SUCCEED <2>执行失败时返回FAIL
参数 <1>dbproc:已经连接到某个数据库的句柄
<2>cmdstrmg:要执行的sql命令
注意:dbcmd()函数其实是将SQL命令保存到dbproc指针指向的命令缓存中,不会立即执行
SQL命令执行函数dbsqlexec()
函数原型 RETCODE dbsqlexec(DBPROCESS* dbproc);
返回值 <1>成功时返回SUCCEED <2>失败时返回FAIL
参数 dbproc:保存了SQL命令的数据库连接句柄
SQL命令执行成功与否的判断函数dbresults()
函数原型 RETCODE dbresults(DBPROCESS* dbproc);
返回值 <1>函数执行成功时返回SUCCEED <2>函数执行失败时返回FAIL
参数 dbproc:运行了dbsqlexec()函数之后的数据库连接句柄
SQL命令查询结果返回函数dbind()
函数原型 RETCODE dbind(DBPROCESS* dbproc, int column, int vartype, DBINT valen, BYTE* varaddr);
返回值 <1>函数执行成功时返回SUCCEED <2>函数执行失败时返回FAIL
参数 <1>dbproc:保存了函数运行结果的数据库连接句柄
<2>column:你在数据库中查找到的数据的列数, 顺序以sql语句为准, 起始数据为1
<3>vartype:数据的类型, 既是要接收从数据库取出来的本机数据的类型
<4>varlen:保存取出数据的本地内存的大小
<5>varaddr:保存取出数据的本地内存的地址指针
结果集合中下一行数据查询函数dbnextrow()
函数原型 RETCODE dbnextrow(DBPROCESS* dbproc);
返回值 <1>NO_MORE_ROWS:结果集中没有更多的数据
参数 <1>dbproc:保存了查询结果的数据库连接句柄
关闭数据库连接函数dbclose()
函数原型 void dbclose(DBPROCESS* dbproc);
参数 dbproc:一个连接好数据库的连接句柄
数据库连接测试
新建一个文本文件,重命名为test.cpp,并写入以下内容:
#include
#include
#include
#include
#include //freetds头文件
#include //freetds头文件
int main(void)
{
char szUsername[32] = "sa";
char szPassword[32] = "Robot123456";
char szDBName[32] = "TestDB"; //数据库名
char szServer[32] = "127.0.0.1:1433";//数据库服务器:端口
//初始化db-library
dbinit();
//连接数据库
LOGINREC *loginrec = dblogin();
DBSETLUSER(loginrec, szUsername);
DBSETLPWD(loginrec, szPassword);
DBPROCESS *dbprocess = dbopen(loginrec, szServer);//连接数据库
if(dbprocess == FAIL)
{
printf("Conect to MS SQL SERVER fail, exit!\n");
return -1;
}
printf("Connect to MS SQL SERVER success!\n");
if(dbuse(dbprocess, szDBName) == FAIL)
printf("Open database failed!\n");
else
printf("Open database success!\n");
//关闭数据库连接
dbclose(dbprocess);
return 0;
}
打开一个终端,进入该文件所在目录并输入以下命令进行编译:
g++ test.cpp -o test
结果报错:
未定义的引用,说明编译时没有连接包含该函数定义的动态链接库(如果是“未声明的引用”,则是因为包含该函数声明的头文件未成功添加)。这里添加上sybdb动态链接库再重新编译:
g++ test.cpp -o test -l sybdb
结果显示上述报错消失,但又产生了新的报错信息:
意思是共享链接库sybdb中调用了其他共享链接库中的函数,而包含这些函数的共享链接库未连接。通过查询搜索引擎得知,openssl提供了两个库:ssl 和 crypto,如果要二次开发需要连接这两个共享库。于是添加上这两个库再重新编译:
g++ test.cpp -o test -l sybdb -l ssl -l crypto
可成功完成编译,并生产可执行文件test。在终端中运行 ./test 即可运行,运行结果如下说明数据库连接成功: