C++使用ODBC调用数据库
前言:
想用c++操作数据库却不知道怎么做?往下看吧,没有比这全的了。ODBC教程。
- ODBC简介
ODBC是开放式数据库连接。与JDBC一样,ODBC也是一个API,充当客户端应用程序和服务器端数据库之间的接口。
ODBC帮助应用程序从数据库访问数据。用任何语言编写的应用程序都可以使用ODBC访问不同类型的数据库,因此,它被认为是独立于语言和平台的。与JDBC一样,ODBC aslo提供ODBC驱动程序,可将用任何语言编写的应用程序请求转换为数据库可理解的语言。
ODBC是最广泛使用的,并且可以理解许多不同的编程语言。但它的代码很复杂,难以理解。
- ODBC编程的步骤
- 配置数据源
- 初始化环境
- 连接数据库
- 拼接SQL语句执行
- 返回结果
- 释放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 | SQL_CP_OFF : 默认值,关闭连接池 SQL_CP_ONE_PER_DRIVER :连接池中的每一个连接都必须属于同一个驱动下的连接 SQL_CP_ONE_PER_HENV :连接池中的每一个连接都申请于同一个环境句柄 |
SQL_ATTR_CP_MATCH | 当调用 SQLConnect或者 SQLDriverConnect 时,该参数用于决定从连接池中选择连接的精度。 SQL_CP_STRICT_MATCH:默认值,连接的属性和驱动池中的连接完全一致时才会采用。 SQL_CP_RELAXED_MATCH :并非匹配所有的连接属性。 |
SQL_ATTR_ODBC_VERSION | 根据取值决定ODBC表现出的版本特性。 · SQL_OV_ODBC3 · SQL_OV_ODBC2 |
SQL_ATTR_OUTPUT_NTS | 确定返回字符串的结束符。 默认值为 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 Docshttps://docs.microsoft.com/zh-cn/sql/odbc/reference/syntax/odbc-api-reference?view=sql-server-ver15