ODBC 接口

ODBC(Open Database Connectivity,开放数据库连接)是 Microsoft公司为应用程序访问关系型数据库时提供的一组标准接口规范。ODBC对不同的关系型数据库提供了统一的API,使用该AP来访问任何提供了ODBC驱动程序的数据库。

ODBC的构成

  • 应用程序-> 执行调用ODBC接口,ODBC AP不能直接访问数据库,必须通过驱动程序管理器与数据库交换信息。

  • 驱动程序-> 每种数据库引擎都提供自己的ODBC驱动程序,并且需要向ODBC驱动程序管理器注册

  • 驱动程序管理器-> ODBC提供了一个驱动程序管理器来管理对多个DBMS的同时访问。

  • 数据源-> 包含了数据库位置和数据库类型等信息,实际上是种数据连接的抽象。

ODBC的优点

以统一的方式处理所有的数据库,ODBC开发的程序可以在不同的关系型数据库(SQL Server,Mysql,Oracle,HGDB等)之间自由切换。

功能强大丰富,提供了异步操作,事务处理等高级功能。

开发环境搭建

软件 版本
HGDB 安全版V4、企业版v5及以上版本
IDE visual Studio 2019

前提条件

连接瀚高数据库需要使用瀚高的ODBC驱动程序,下面介绍如何在外网下载瀚高的ODBC和其使用方法。

通过百度网盘即可下载瀚高的ODBC(瀚高数据库V4.5.4及之后版本安装后会自带ODBC驱动,驱动位置:/opt/HighGo4.5.4-see/etc/drivers/ODBC)

链接:https://pan.baidu.com/s/1CrUNnRJqFXUG9gODR6WMXA

提取码:5rbm

下载解压之后会生成ODBC_FT2000.tar.gz、ODBC_Loongson.tar.gz、ODBC-Centos.rar、ODBC-Windows.rar 4个压缩包,分别对应飞腾、龙芯、CentOs、Windows

详细对应关系见下表:

驱动包名称 对应芯片
ODBC_FT2000.tar.gz 飞腾
ODBC_Loongson.tar.gz 龙芯
ODBC-Centos.rar Centos
ODBC-Windows.rar Windows

根据实际版本选择对应的ODBC驱动即可。

windows安装

1、双击hgdbodbc-x86-64-20201028.msi直接安装:

image.png

2、安装完成后在控制面板–>管理工具:

image.png

3、点击添加:

image.png

4、选择PostgreSQL Unicode(64):

image.png

5、输入数据库信息,点击test:

image-20220517103027083

6、出现以下信息说明连接成功:

image-20220517103514811

Linux安装

1、本次使用V4.5.7版本

2、UNIX/Linux系统下的驱动程序管理器主要有unixODBC和iODBC,在这里使用unixODBC2.3.1作为连接数据库的组件。

3、需要准备unixODBC环境:

​ 安装unixODBC:执行命令 yum install unixODBC 和 yum install unixODBC-devel

1、修改配置文件

进入/opt/HighGo4.5.7-see/etc/drivers/ODBC/unixODBC/etc目录修改odbcinst.ini、odbc.ini:

odbcinst.ini添加如下信息:

[HighGo]
Description = ODBC for HighGo
Driver = /opt/HighGo4.5.7-see/etc/drivers/ODBC/psqlODBC/lib/psqlodbcw.so
Driver64 = /opt/HighGo4.5.7-see/etc/drivers/ODBC/psqlODBC/lib/psqlodbcw.so
FileUsage =1

odbc.ini添加如下信息:

[HighGo457]
Driver = HighGo
Description = HighGo DSN
Servername = 192.168.2.5
Database = test
Username = test
Password = test
Port = 5866
ReadOnly = No

注意:odbc.ini中的Driver对应的是odbcinst.ini中最上边中括号中的内容。

2、测试连接

到/opt/HighGo4.5.7-see/etc/drivers/ODBC/unixODBC/bin目录下执行

说明:-v 的作用是,一旦报错,可以展示报错详情

[root@centos-min4 bin]# ./isql -v HighGo457

+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL>

注意:需要添加环境变量ODBCSYSINI=/opt/HighGo4.5.7-see/etc/drivers/ODBC/unixODBC/etc

示例代码

Odbc_Demo.cpp

//包含头文件
#include<Windows.h>
#include <sql.h>
#include <sqlext.h>
#include<sqltypes.h>
#include <tchar.h>
#include <iostream>
using namespace std;

int main()
{
//设置为中文
_wsetlocale(LC_ALL, L"chs");

SQLRETURN ret = SQL_ERROR;

//分配ODBC环境句柄
SQLHENV hEnv = NULL;
ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
if (SQL_SUCCESS == ret)
{
wcout << _T("环境句柄分配成功!") << endl;
}
else
{
return -1;
}

//设定ODBC的版本
ret = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);

//分配数据库连接句柄
SQLHDBC hDbc = NULL;
ret = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);

//根据DSN ,连接数据库
ret = SQLConnect(hDbc, (SQLTCHAR*)_T("HighGoOdbc"), SQL_NTS, (SQLTCHAR*)_T("test"), SQL_NTS, (SQLTCHAR*)_T("test"), SQL_NTS);
if ((ret == SQL_SUCCESS) || (ret == SQL_SUCCESS_WITH_INFO))
{
wcout << _T("数据库连接成功!") << endl;
}
else if (ret == SQL_ERROR)
{
SQLTCHAR state[128] = { 0 };
SQLTCHAR msg[128] = { 0 };
//获取错误信息
ret = SQLError(hEnv, hDbc, NULL, state, NULL, msg, sizeof(msg), NULL);
wcout << state << " " << msg << endl;
}

//分配语句句柄
SQLHSTMT hStmt = NULL;
ret = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt);

//////////-----插入数据--------start

//没 “?”简单版本
//SQLTCHAR insert_sql[] = _T("INSERT INTO student (name,age) VALUES('李白',23) ");
//ret = SQLPrepare(hStmt, insert_sql, SQL_NTS);


//复杂版本
SQLTCHAR insert_sql[] = _T("INSERT INTO student (name,age) VALUES(?,?) ");
ret = SQLPrepare(hStmt, insert_sql, SQL_NTS);

//复杂版本下的参数传递到SQL语句中
SQLTCHAR name[32];
SQLSMALLINT age=40;

//绑定SQL语句的参数
ret = SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR,SQL_CHAR, 50, 0, (SQLPOINTER)name,0, NULL);
ret = SQLBindParameter(hStmt, 2, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_SMALLINT, 0, 0, (SQLPOINTER)&age, 0, NULL);

//name赋值
strcpy_s((char*)name, _countof(name), "Miller");

//执行SQL语句
ret = SQLExecute(hStmt);
if ((ret == SQL_SUCCESS) || (ret == SQL_SUCCESS_WITH_INFO))
{
SQLLEN n = 0;
ret = SQLRowCount(hStmt, &n);//查询被影响的行数
if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
{
_tprintf(_T("插入%d行数据成功!\n"), n);
}
}
else if (ret == SQL_ERROR)
{
SQLTCHAR state[128] = { 0 };
SQLTCHAR msg[128] = { 0 };
//获取错误信息,注意填写语句句柄
ret = SQLError(hEnv, hDbc, hStmt, state, NULL, msg, sizeof(msg), NULL);
wcout << state << " " << msg << endl;
}

//////////-----插入数据--------end


//////////-----查询数据--------start

//SQL查询语句
SQLTCHAR select_sql[] = _T("SELECT * FROM student ");

//执行SQL语句
ret = SQLExecDirect(hStmt, select_sql, SQL_NTS); //SQL_NTS自动计算sql语句的长度
if ((ret == SQL_SUCCESS) || (ret == SQL_SUCCESS_WITH_INFO))
{
//查询之后,所有数据放到了一块缓冲区,我们需要把他分离出来
int id = 0;
CHAR name[32] = { 0 };
short age = 0;
//绑定字段
SQLLEN len = SQL_NTS;
SQLBindCol(hStmt, 1, SQL_C_LONG, &id, sizeof(id), 0);
SQLBindCol(hStmt, 2, SQL_C_CHAR, &name, sizeof(name), &len);
SQLBindCol(hStmt, 3, SQL_C_SHORT, &age, sizeof(age), 0);
//逐行遍历,获取数据
ret = SQLFetch(hStmt);
while (ret != SQL_NO_DATA)
{
wcout << id << "\t" << name << "\t" << age << endl;
//每次清除一下上行的旧数据,保证下次获取的数据干净
id = 0;
ZeroMemory(name, sizeof(name));
age = 0;
//获取下一行缓冲区的数据填充到id,name,age
ret = SQLFetch(hStmt);
}

SQLLEN n = 0;
ret = SQLRowCount(hStmt, &n);//查询被影响的行数(适用于SELECT ,INSERT,UPDATE,DELETE操作)
if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
{
_tprintf(_T("查询%d行数据成功!\n"), n);
}
}
else if (ret == SQL_ERROR)
{
SQLTCHAR state[128] = { 0 };
SQLTCHAR msg[128] = { 0 };
//获取错误信息,注意填写语句句柄
ret = SQLError(hEnv, hDbc, hStmt, state, NULL, msg, sizeof(msg), NULL);
wcout << state << " " << msg << endl;
}

///////// -----查询数据--------end

//释放语句句柄
if (hStmt)
{
ret = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
}

//关闭数据库连接
ret = SQLDisconnect(hDbc);
if (ret == SQL_SUCCESS)
{
wcout << _T("关闭数据库连接成功!") << endl;
}

//释放连接句柄
if (hDbc)
{
ret = SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
}

//释放环境句柄
if (hEnv)
{
ret = SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
}

return 0;
}

执行结果:

image-20220427224911938

image-20220427224928520