C++使用ODBC调用数据库

前言:

        想用c++操作数据库却不知道怎么做?往下看吧,没有比这全的了。ODBC教程。

  • ODBC简介

ODBC是开放式数据库连接。与JDBC一样,ODBC也是一个API,充当客户端应用程序和服务器端数据库之间的接口。

ODBC帮助应用程序从数据库访问数据。用任何语言编写的应用程序都可以使用ODBC访问不同类型的数据库,因此,它被认为是独立于语言和平台的。与JDBC一样,ODBC aslo提供ODBC驱动程序,可将用任何语言编写的应用程序请求转换为数据库可理解的语言。

ODBC是最广泛使用的,并且可以理解许多不同的编程语言。但它的代码很复杂,难以理解。

  • ODBC编程的步骤
  1. 配置数据源
  2. 初始化环境
  3. 连接数据库
  4. 拼接SQL语句执行
  5. 返回结果
  6. 释放ODBC连接
  • 需要用到的头文件

#include<Windows.h>

#include <sql.h>

#include <sqlext.h>

#include<sqltypes.h>

  • 配置数据源

使用SQLCongifDataSource()函数配置数据源

BOOL SQLConfigDataSource(HWND hwndParent,UINT fRequest, LPCSTR lpszDriver, LPCSTR lpszAttributes);

参数和语法:

hwndParent:指定为 ODBC 驱动程序管理器或特定 ODBC 驱动程序所创建的任何对话框的所有者的窗口,用于从用户那里获取有关新数据源的附加信息。 如果 lpszAttributes 参数没有提供足够的信息,则会出现一个对话框。 HwndParent参数可以为 NULL。

fRequest:要执行的操作,可以选以下参数

   ODBC_ADD_DSN: 增加一个新数据源

   ODBC_CONHG_DSN: 配置(修改)一个已经存在的数据源

   ODBC_REMOVE_DSN: 删除一个已经存在的数据源

   ODBC_ADD_SYS_DSN:. 增加一个新的系统数据源

   ODBC_CONFIG_SYS_DSN: 更改一个已经存在的系统数据源

   ODBC_REMOVE_SYS_DSN:. 删除一个已经存在的系统数据源

lpszDriver:驱动程序说明。 这是向用户显示的名称,而不是 DLL) (物理驱动程序名称。

lpszAttributes:"Keyname = value" 形式的特性列表。 这些字符串通过空终止符分隔,列表末尾有两个连续的 null 终止符。 这些属性主要是默认的特定于驱动程序的条目,它们进入到新数据源的注册表中。 此函数的 ODBC API 参考中未提到的一个重要的关键是 "DSN" ( "数据源名称" ) ,它指定新数据源的名称。 其余条目特定于新数据源的驱动程序。 通常不需要提供所有条目,因为驱动程序可以提示用户提供新值的对话框。 (将 HwndParent 设置为 NULL 以引发此问题。 ) 你可能需要显式提供默认值,以便不会提示用户。

分两种情况,一种是在本地,

DSN:数据源名字。

DBQ:数据库文件全路径。

另一种是远程,

DSN:数据库名字。

SERVER:远程数据库地址。

DATABASE:数据库名。

  • ODBC对象

1.SQLHENV: 环境句柄 ,
2.SQLHDBC: 连接句柄
3.SQLHSTMT: SQL语句句柄
4.SQLHDESC: 描述符句柄

  • 分配句柄

分配环境句柄

使用SQLAllocHandle(SQLSMALLINT HandleType,SQLHANDLE InputHandle,SQLHANDLE *OutputHandlePtr)分配句柄

Handle Type:

类型

参数

申请环境句柄

SQL_HANDLE_ENV

申请连接句柄

SQL_HANDLE_DBC

申请描述符句柄

SQL_HANDLE_DESC

申请语句句柄

SQL_HANDLE_STMT

InputHandle:[输入]要分配新句柄的上下文中的输入句柄。 如果 已SQL_HANDLE_ENV HandleType ,则SQL_NULL_HANDLE。 如果 已SQL_HANDLE_DBC HandleType ,则它必须是环境句柄,如果它SQL_HANDLE_STMT或SQL_HANDLE_DESC,则它必须是连接句柄。

OutputHandlePtr:[输出]指向缓冲区的指针,该缓冲区将句柄返回到新分配的数据结构。

使用SQLFreeHandle(SQLSMALLINT HandleType,  SQLHANDLE Handle)释放句柄。

返回值:SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_ERROR 或 SQL_INVALID_HANDLE。

  • 环境句柄

连接数据库前先使用SQLAllocHandle(SQLSMALLINT HandleType,SQLHANDLE InputHandle,SQLHANDLE *OutputHandlePtr)分配环境句柄,然后设置属性。

使用SQLRETURN SQLSetEnvAttr(SQLHENV EnvironmentHandle,SQLINTEGER Attribute,SQLPOINTER ValuePtr,SQLINTEGER StringLength);设置属性

EnvironmentHandle:环境句柄

Attribute:输入变量

ValuePtr:输入变量

Attribute取值

ValuePtr取值

SQL_ATTR_CONNECTION_POOLING
(ODBC 3.0)

SQL_CP_OFF : 默认值,关闭连接池

SQL_CP_ONE_PER_DRIVER :连接池中的每一个连接都必须属于同一个驱动下的连接

SQL_CP_ONE_PER_HENV :连接池中的每一个连接都申请于同一个环境句柄

SQL_ATTR_CP_MATCH
(ODBC 3.0)

当调用 SQLConnect或者 SQLDriverConnect 时,该参数用于决定从连接池中选择连接的精度。

SQL_CP_STRICT_MATCH:默认值,连接的属性和驱动池中的连接完全一致时才会采用。

SQL_CP_RELAXED_MATCH :并非匹配所有的连接属性。

SQL_ATTR_ODBC_VERSION
(ODBC 3.0)

根据取值决定ODBC表现出的版本特性。 

· SQL_OV_ODBC3

· SQL_OV_ODBC2

SQL_ATTR_OUTPUT_NTS
(ODBC 3.0)

确定返回字符串的结束符。

默认值为 SQL_TRUE返回’/0’结束的字符串。

SQL_FALSE相反。

StringLength:如果ValuePtr为一个整型指针,则可以被忽略。如果为二进制或字符串,那么就需要再次放入其长度。

用法:

必须先设置ODBC版本,才可以设置其他属性。

1. 设置版本ODBC 3.X

rs= SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);

2. 设置SQL_CP_ONE_PER_DRIVER

rs= SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);

rs= SQLSetEnvAttr(henv,SQL_ATTR_CONNECTION_POOLING,(SQLPOINTER)SQL_CP_ONE_PER_DRIVER ,SQL_IS_INTEGER);

3. 关闭线程池

rs= SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);

rs= SQLSetEnvAttr(henv,SQL_ATTR_CONNECTION_POOLING,(SQLPOINTER)SQL_CP_OFF,SQL_IS_INTEGER);

4. 设置SQL_CP_ONE_PER_HENV

rs= SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);

rs= SQLSetEnvAttr(henv,SQL_ATTR_CONNECTION_POOLING,(SQLPOINTER)SQL_CP_ONE_PER_HENV ,SQL_IS_INTEGER);

5. 设置严格匹配

rs= SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);

rs= SQLSetEnvAttr(henv,SQL_ATTR_CP_MATCH,(SQLPOINTER)SQL_CP_STRICT_MATCH,SQL_IS_INTEGER);

6. 设置非严格匹配

rs= SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);

rs= SQLSetEnvAttr(henv,SQL_ATTR_CP_MATCH,(SQLPOINTER)SQL_CP_RELAXED_MATCH ,SQL_IS_INTEGER);

7. 设置返回’/0’结束字符串

rs= SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);

rs= SQLSetEnvAttr(henv,SQL_ATTR_OUTPUT_NTS,(SQLPOINTER)SQL_TRUE,SQL_IS_INTEGER);

8. 设置非’/0’字符串

rs= SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);

rs= SQLSetEnvAttr(henv,SQL_ATTR_OUTPUT_NTS,(SQLPOINTER)SQL_FALSE,SQL_IS_INTEGER);

返回值:SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_INVALID_HANDLE, or SQL_ERROR.

  • 连接句柄

设置好环境后,使用SQLAllocHandle(SQLSMALLINT HandleType,SQLHANDLE InputHandle,SQLHANDLE *OutputHandlePtr)分配连接句柄,然后使用SQLConnect(SQLHDBC ConnectionHandle,SQLCHAR * ServerName, SQLSMALLINT NameLength1,SQLCHAR * UserName,SQLSMALLINT NameLength2, SQLCHAR *  Authentication,SQLSMALLINT     NameLength3);连接数据库

参数:

ConnectionHandle:[输入] 连接句柄。

ServerName:[输入]数据源名称。 数据可能位于与程序相同的计算机上,或者位于网络上另一台计算机中。 有关应用程序如何选择数据源的信息,请参阅 选择数据源或驱动程序

NameLength1:[输入]ServerName 的长度( 以字符表示)。

UserName:[输入]用户标识符。

NameLength2:[输入]*UserName 的长度( 以字符表示)。

Authentication:[输入]身份验证字符串 (密码) 。

NameLength3:[输入]*身份验证的长度( 以字符表示)。

注:NameLength设置SQL_NTS就好,意思是遇见’\0’为止

返回值:SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_ERROR、SQL_INVALID_HANDLE 或 SQL_STILL_EXECUTING。

  • SQL语句句柄

执行SQL语句之前我们先用SQLAllocHandle(SQLSMALLINT HandleType,SQLHANDLE InputHandle,SQLHANDLE *OutputHandlePtr)分配句柄,之后执行SQL语句,之后查看影响行数。

SQLExecDirect(SQLHSTMT StatementHandle,SQLCHAR * StatementText,SQLINTEGER TextLength);如果语句中存在任何参数, SQLExecDirect将使用参数标记变量的当前值执行可准备对象语句。 SQLExecDirect是提交用于一次性执行的 SQL 语句的最快方法。

/*SQLRETURN SQLPrepare(SQLHSTMT StatementHandle,SQLCHAR * StatementText,SQLINTEGER    TextLength);

SQLPrepare准备 SQL 字符串以执行。*/

参数及说明:

StatementHandle:语句句柄。

StatementText:要执行 SQL 语句。

TextLength:*StatementText 的长度(字符)。

SQLRETURN SQLFetch( SQLHSTMT StatementHandle);从结果集中获取下一个数据行集并返回所有绑定列的数据。

参数

类型

含义

StatementHandle

输入参数

语句句柄

SQLGetData(SQLHSTMT StatementHandle,SQLUSMALLINT Col_or_Param_Num,SQLSMALLINT TargetType,SQLPOINTER TargetValuePtr,SQLLEN         BufferLength,SQLLEN * StrLen_or_IndPtr);  检索指定列的内容,并将结果返回给第四个参数。

参数:

StatementHandle:语句句柄

Col_or_Param_Num:为了检索列数据,它是要为其返回数据的列的编号。结果集列按从 1 开始的递增列顺序进行编号。书签列是列号 0;仅当启用了书签时,才能指定此值。

TargetType:TargetValuePtr 缓冲区的 C数据类型 的类型标识符。

TargetValuePtr:(输出参数)指向要返回数据的缓冲区的指针, TargetValuePtr不能为NULL

BufferLength:TargetValuePtr 缓冲区的长度(以字节为单位)

在返回可变长度的数据(如字符或二进制数据)时,驱动程序使用 BufferLength 避免写入 * TargetValuePtr 缓冲区的末尾。 请注意,将字符数据返回到 * TargetValuePtr 时,驱动程序会计算 null 终止字符。 因此,TargetValuePtr 必须包含 null 终止字符的空间,否则驱动程序将截断数据。 当驱动程序返回固定长度的数据(如整数或日期结构)时,驱动程序将忽略 BufferLength, 并假定缓冲区足够大以容纳数据。

StrLen_or_IndPtr:指向要返回长度或指示器值的缓冲区的指针如果这是空指针,则不返回长度或指示器值。 当正在提取的数据为 NULL 时,这会返回错误。

十、释放

SQLRETURN SQLDisconnectSQLHDBC ConnectionHandle);  关闭与特定连接句柄关联的连接

SQLRETURN SQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle);释放与特定环境、连接、语句或描述符句柄相关联的资源,此函数是用于释放句柄的通用函数,取代了 ODBC 2.0 函数SQLFreeConnect(用于释放连接句柄)和SQLFreeEnv(用于释放环境句柄)。

SQLFreeConnect和SQLFreeEnv在 ODBC 3*.x* 中均已弃用。

SQLFreeHandle还替换了 ODBC 2.0 函数SQLFreeStmt(带有 SQL_DROP Option)以释放语句句柄。

十一、扩展

        本文的内容有点多,如果你看的头疼或者文中内容不全可以参考以下链接:ODBC API 参考 - ODBC API Reference | Microsoft Docs

通过ODBC连接access数据库 odbc连接数据库实例_c++

https://docs.microsoft.com/zh-cn/sql/odbc/reference/syntax/odbc-api-reference?view=sql-server-ver15