ODBC方式操作ACCESS数据库OLE类型字段

您所在的位置:网站首页 ole对象存放二进制的方式 ODBC方式操作ACCESS数据库OLE类型字段

ODBC方式操作ACCESS数据库OLE类型字段

2024-07-09 19:16| 来源: 网络整理| 查看: 265

ODBC方式操作ACCESS数据库OLE类型字段

在实际项目的过程中,往往需要在数据库中存储图片等二进制数据。这篇博客主要介绍下怎么用c++语言和ACCESS数据库完成这项任务。包括两个部分:文件的存储、文件的读取。 此外,连接数据库的方式有多种,包括:ADO、ODBC、OLE等。这篇博客只介绍ODBC方式。

存储数据 CFile file(filepath,CFile::modeRead); //打开文件 int len = file.GetLength(); //获取文件字节数 HGLOBAL hm = ::GlobalAlloc(GMEM_MOVEABLE,len); //分配len大小的全局空间,作为缓冲区 LPVOID lp = ::GlobalLock(hm) ; //这一步是必须的 int n = file.Read(lp,len) ; // 将文件内容读取到缓冲区,返回的n表示读取的长度,n=len 那么就对了 CDatabase dbase; // 这里假设dbase已经正确连接数据库 CRecordset cr(&dbase); SQLHSTMT hstmt = cr.m_hstmt; //statement句柄 SQLWCHAR * cmd = _T("insert into tbName (colName) values(?)") //注1 SQLRETURN ret = SQLPrepare(htsmt, cmd, SQL_NTS); SQLLEN sqllen = len; SQLBindParameter(hstmt,1,SQL_PARAM_INPUT,SQL_C_BINARY,SQL_VARBINARY,len,0,lp,len,&sqllen); //注2 ret = SQLExecute(hstmt); //执行SQL语句,完成存储操作,ret = 0,表示成功 cr.close(); dbase.close(); ::GlobalUnLock(lp); ::GlobalFree(hm);

注1:这个语句是具体的SQL语句,在这里是往colName字段插入我们的OLE类型数据(插入后在ACCESS中显示的是“长二进制数据”)。values中的“?”很重要,其实就是占位符的意思,告诉数据库引擎,这里是需要绑定参数的。 注2:SQLBindParameter函数将缓冲区中的数据与SQL语句中需要的数据绑定,其实就是告诉数据库去哪读取需要的数据。该函数的原型是:

SQLRETURN SQLBindParameter( SQLHSTMT StatementHandle, // statement句柄 SQLUSMALLINT ParameterNumber, // 参数位于语句中的序号,最小为1 SQLSMALLINT InputOutputType, // 入参/出参类型标识 SQLSMALLINT ValueType, // 对应的C数据类型标识 SQLSMALLINT ParameterType, // 对应的SQL数据类型标识 SQLULEN ColumnSize, // 字段长度,其实就是ACCESS数据库中对应插入字段的长度 SQLSMALLINT DecimalDigits, // 如果是浮点数,则对应字段精度,否则为0 SQLPOINTER ParameterValuePtr, // 参数缓存区指针 SQLLEN BufferLength, // 缓存区长度 SQLLEN * StrLen_or_IndPtr); //对于非字符串,用于表示参数字节长度;对于字符串,可用SQL_NTS值。

需要注意的是参数ValueType和ParameterType,需要对应起来,不然读取的时候会出现错读的现象。对于二进制数据,就可以使用SQL_C_BINARY和SQL_VARBINARY。 还有就是ColumnSize参数。这个参数是表示数据库字段宽度:如果数据库中对应字段的整数型,那ColumnSize = 4;如果是浮点型,那么就是8;如果是字符,那么就是设置的字符长度(最大是255);在这里是OLE对象类型,这个类型在ACCESS数据库中没有长度设置(好像最大是一个G),所以我就用的存储所需的实际大小值。 BufferLength和StrLen_or_IndPtr不要混淆,对于存储二进制数据,BufferLength表示参数缓冲区的大小,StrLen_or_IndPtr表示的是实际需要的参数大小;这两个是可以不一样的,因为缓冲区完全可以设置的比需要的大。这是在本例中,设置的大小是一样的。

读取二进制数据 CDatabase dbase; // 这里假设dbase已经正确连接数据库 CRecordset rs(&dbase); CString cmd = _T("select colNmae,lenb(colName) as len from table "); if (rs.open(CRecordeset::forwardOnly,cmd)) { while (!rs.IsEOF()) { CDBVariant variant; rs.GetFieldValue(_T("colName"),variant); LPVOID pdata = ::GlobalLock(variant.m_pbinary->m_hdata); rs.GetFieldValue(_T("len"),variant); int len = variant.m_iVal; //从pdata指针开始读取len长度字节,即为所需的内容 ::GlobalUnLock(pdata); } }

第一次写博客,希望大家能够不吝指正!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3