MariaDB + Visual Studio 2017 环境下的 ODBC 入门开发

参考:

Easysoft公司提供的ODBC教程

微软提供的ODBC文档

环境:

  • Windows 10 x64 1803
  • MariaDB TX 10.2.14 x64
  • MariaDB ODBC Connector 3.0.3 x64
  • Visual Studio 2017 Community 15.6.7

安装ODBC驱动并配置数据源:

先安装ODBC驱动。根据自身需求选择32或64位版本。我选择了64位版本。

打开ODBC数据源管理程序,点击右侧的“添加”按钮,添加用户DSN。如图操作。

后面按照默认配置,点击Next即可。

编写ODBC程序:

1         引入头文件:


#include <iostream>

#include
<windows.h>

#include
<sqlext.h>

2         定义一个检查错误的宏:


#define ODBC_CHECK(x) \

{\

if (!SQL_SUCCEEDED(x))\

{\

std::cout
<< SQL error occurred at line << LINE << .;\

getchar();\

exit(
-1);\

}\

}

3         ODBC初始化,为ODBC分配环境句柄

(分配环境句柄:注意,这里使用了新版的ODBC API SQLAllocHandle**,而不是SQLAllocEnv**)


    // SQL Handle of ENVironment

SQLHENV env;

ODBC_CHECK(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE,
&env)); // SQLAllocEnv

  ODBC_CHECK(SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3,
0));

4         建立应用程序与ODBC数据源的连接

(分配连接句柄:注意,这里使用了新版的ODBC API SQLAllocHandle**,而不是SQLAllocConnect**)


    // SQL Handle of DB Connection

SQLHDBC dbc;

SQLCHAR dbcConfOut[
256];

ODBC_CHECK(SQLAllocHandle(SQL_HANDLE_DBC, env,
&dbc)); // SQLAllocConnect

ODBC_CHECK(SQLSetConnectAttr(dbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)
5, 0));

(连接数据源:可以使用SQLConnect**,也可以使用SQLDriverConnect;可以手动指定DSN名字,也可以通过弹出窗口来指定)**


    // specify manually

ODBC_CHECK(SQLDriverConnect(dbc, NULL, (SQLCHAR
*)DSN=MariaDB;, SQL_NTS,

dbcConfOut,
sizeof(dbcConfOut), NULL, SQL_DRIVER_COMPLETE)); // SQLConnect

// specify by popup window

//ODBC_CHECK(SQLDriverConnect(dbc, GetDesktopWindow(), NULL, SQL_NTS,

// dbcConfOut, sizeof(dbcConfOut), NULL, SQL_DRIVER_COMPLETE)); // SQLConnect

(显示连接成功的信息)


    std::cout << Connected! << std::endl

<< ConnStrIn = << dbcConfOut << std::endl;

SQLCHAR dbmsName[
256];

ODBC_CHECK(SQLGetInfo(dbc, SQL_DBMS_NAME, (SQLPOINTER)dbmsName,
sizeof(dbmsName), NULL));

SQLCHAR dbmsVer[
256];

ODBC_CHECK(SQLGetInfo(dbc, SQL_DBMS_VER, (SQLPOINTER)dbmsVer,
sizeof(dbmsVer), NULL));

std::cout
<< DBMS Name = << dbmsName << std::endl

<< DBMS Version = << dbmsVer << std::endl;

(分配语句句柄:注意,这里使用了新版的ODBC API SQLAllocHandle**,而不是SQLAllocStmt**)


    // SQL Handle of STateMenT

SQLHSTMT stmt;

ODBC_CHECK(SQLAllocHandle(SQL_HANDLE_STMT, dbc,
&stmt)); // SQLAllocStmt

5         利用SQLExecDirect语句,实现数据库应用程序对数据库的建立、查询、修改、删除等 

(建立一个循环,一直接收并执行用户的SQL**的语句,直到用户退出)**


    const int queryLen = 1024;

SQLCHAR query[queryLen];

std::cout
<< Please input your SQL query. Type CTRL+Z to quit. << std::endl

<< dbmsName << >;

while (fgets((char*)query, queryLen - 1, stdin))

{

if (query[0] == \n)

{

std::cout
<< dbmsName << >;

continue;

}

switch (SQLExecDirect(stmt, query, SQL_NTS))

{

case SQL_SUCCESS_WITH_INFO:

case SQL_SUCCESS:

{

SQLSMALLINT col;

SQLNumResultCols(stmt,
&col);

// SELECT

if (col > 0)

{
// 2 methods: SQLGetData() and SQLBindCol()

// SQLGetData() is adopted here

char buf[512];

SQLUSMALLINT colidx;

// print column names

for (colidx = 1; colidx <= col; ++colidx)

{

SQLColAttribute(stmt, colidx, SQL_DESC_NAME,

buf,
sizeof(buf), NULL, NULL);

std::cout
<< buf << ;

}

std::cout
<< std::endl;

// iterate each row

unsigned row
= 0; // row counter

while (SQL_SUCCEEDED(SQLFetch(stmt)))

{

++row;

// iterate each column

for (colidx = 1; colidx <= col; ++colidx)

{

SQLLEN indicator;

if (SQL_SUCCEEDED(SQLGetData(stmt, colidx, SQL_C_CHAR,

buf,
sizeof(buf), &indicator)))

{

if (indicator == SQL_NULL_DATA) strcpy(buf, NULL);

std::cout
<< buf << ;

}

}

std::cout
<< std::endl;

}

if (row == 1) { std::cout << 1 row in set. << std::endl; }

else { std::cout << row << rows in set. << std::endl; }

}

// CREATE, UPDATE, DELETE, etc.

else

{

SQLLEN row;

ODBC_CHECK(SQLRowCount(stmt,
&row));

if (row == 1) { std::cout << 1 row affected. << std::endl; }

else { std::cout << row << rows affected. << std::endl; }

}

break;

}

case SQL_ERROR:

{

std::cout
<< Returned SQL_ERROR. << std::endl;

break;

}

default:

{

std::cout
<< Unknown SQLRETURN. << std::endl;

}

}

ODBC_CHECK(SQLFreeStmt(stmt, SQL_CLOSE));

std::cout
<< dbmsName << >;

}

6         检索查询结果集 

7         结束数据库应用程序


    // release resources

ODBC_CHECK(SQLFreeHandle(SQL_HANDLE_STMT, stmt));

ODBC_CHECK(SQLDisconnect(dbc));

ODBC_CHECK(SQLFreeHandle(SQL_HANDLE_DBC, dbc));

ODBC_CHECK(SQLFreeHandle(SQL_HANDLE_ENV, env));

return 0;