收藏 分享(赏)

数据库连接总结c++版(1).doc

上传人:dreamzhangning 文档编号:2207843 上传时间:2018-09-05 格式:DOC 页数:43 大小:264KB
下载 相关 举报
数据库连接总结c++版(1).doc_第1页
第1页 / 共43页
数据库连接总结c++版(1).doc_第2页
第2页 / 共43页
数据库连接总结c++版(1).doc_第3页
第3页 / 共43页
数据库连接总结c++版(1).doc_第4页
第4页 / 共43页
数据库连接总结c++版(1).doc_第5页
第5页 / 共43页
点击查看更多>>
资源描述

1、VC 数据库编程总结(一) +一、访问数据库技术方法. 21、几种是数据库访问方法比较 22、VC 数据库编程几种方法. 2(1)通用方法. 21. ODBC 连接 22. MFC ODBC 连接 33. DAO 连接 54. OLE DB 连接. 5使用 OLEDB 编写数据库应用程序 6使用 OLE DB 读写 SQL Server 95. OLE DB Templates 连接 206. ADO 连接. 21用 ADO 进行数据库编程 22(2)Oracle 专用方法. 291. OCI(Oracle Call Interface)访问. 292. Oracle Object OLE C

2、+ Class Library. 293. 使用 OTL 进行数据库编程. 30OTL 编程实例 30二、据库语句优化 33SQL 语句优化的原则. 33一些常用的 SQL 语句. 34三、数据库优化 36通用优化. 36优化 SQL Server 数据库 37Oracle SQL 性能优化 46DB2 数据库优化. 48四、冷备份与热备份、双机热备与容错. 54一、冷备份 54二、热备份 55双机热备的实现模式 56双机容错的工作原理 57双机容错环境下 Oracle 数据库的具体应用 59双机容错的实现 59需要注意的问题 60数据库编程总结当前各种主流数据库有很多,包括 Oracle,

3、MS SQL Server, Sybase, Informix, MySQL, DB2, Interbase / Firebird, PostgreSQL, SQLite, SAP/DB, TimesTen, MS ACCESS 等等。数据库编程是对数据库的创建、读写等一列的操作。数据库编程分为数据库客户端编程与数据库服务器端编程。数据库客户端编程主要使用 ODBC API、ADO、ADO.NET、OCI、OTL 等方法;数据库服务端编程主要使用 OLE DB 等方法。数据库编程需要掌握一些访问数据库技术方法,还需要注意怎么设计高效的数据库、数据库管理与运行的优化、数据库语句的优化。一、访问数

4、据库技术方法数据库编程分为数据库客户端编程与数据库服务器端编程。数据库客户端编程主要使用ODBC API、ADO、ADO.NET、OCI、OTL 等方法;数据库服务端编程主要使用 OLE DB等方法。1、几种是数据库访问方法比较ODBC API 是一种适合数据库底层开发的编程方法,ODBC API 提供大量对数据源的操作,ODBC API 能够灵活地操作游标,支持各种帮定选项,在所有 ODBC 相关编程中,API 编程具有最高的执行速度。DAO 提供了很好的数据库编程的对象模型.但是,对数据库的所有调用以及输出的数据都必须通过 Access/Jet 数据库引擎,这对于使用数据库应用程序 ,是严

5、重的瓶颈。OLE DB 提供了 COM 接口,与传统的数据库接口相比,有更好的健壮性和灵活性,具有很强的错误处理能力,能够同非关系数据源进行通信。ADO 最主要的优点在于易于使用、速度快、内存支出少和磁盘遗迹小。ADO.NET 是利用数据集的概念将数据库数据读入内存中,然后在内存中对数据进行操作,最后将数据集数据回写到源数据库中。OTL 是 Oracle, Odbc and DB2-CLI Template Library 的缩写,是一个 C+编译中操控关系数据库的模板库,OTL 中直接操作 Oracle 主要是通过 Oracle 提供的 OCI 接口进行,进行操作 DB2 数据库则是通过 C

6、LI 接口来进行,至于 MS 的数据库和其它一些数据库,则 OTL只提供了 ODBC 来操作的方式。当然 Oracle 和 DB2 也可以由 OTL 间接使用 ODBC 的方式来进行操纵。具有以下优点:跨平台;运行效率高,与 C 语言直接调用 API 相当;开发效率高,起码比 ADO.net 使用起来更简单,更简洁;部署容易,不需要 ADO 组件,不需要.net framework 等。2、 VC 数据库编程几种方法VC 数据库编程几种方法,包括 ODBC 连接、MFC ODBC 连接、DAO 连接、OLE DB、OLE DB Templates 连接、ADO、Oracle 专用方法(OCI(

7、Oracle Call Interface)访问、Oracle Object OLE C+ Class Library )。(1 )通用方法1. ODBC 连接ODBC(Open DataBase Connectivity)是 MSOA 的一部分,是一个标准数据库接口。它提供对关系数据库访问的统一接口,实现对异构数据源的一致访问。ODBC 数据访问由以下部分组成:句柄 (Handles):ODBC 使用句柄来标识 ODBC 环境、连接、语句和描述器.缓存区 (Buffers):数据类型 (Data types)一致性级别(Conformance levels)用 ODBC 设计客户端的一般步骤

8、:分配 ODBC 环境分配连接句柄连接数据源构造和执行 SQL 语句获得查询结果断开数据源的连接释放 ODBC 环境ODBC API 是一种适合数据库底层开发的编程方法,ODBC API 提供大量对数据源的操作,ODBC API 能够灵活地操作游标,支持各种帮定选项,在所有 ODBC 相关编程中,API 编程具有最高的执行速度.因此,ODBC API 编程属于底层编程。2. MFC ODBC 连接MFC ODBC 是 MFC 对 ODBC 进行的封装,以简化对 ODBC API 的 调用,从而实现面向对象的数据库编程接口.MFC ODBC 的封装主要开发了 CDatabase 类和 CReco

9、rdSet 类(1) CDatabase 类CDatabase 类用于应用程序建立同数据源的连接。CDatabase 类中包含一个 m_hdbc 变量,它代表了数据源的连接句柄。如果要建立 CDatabase 类的实例 ,应先调用该类的构造函数,再调用 Open 函数,通过调用,初始化环境变量,并执行与数据源的连接。在通过 Close 函数关闭数据源。CDatabase 类提供了对数据库进行操作的函数及事务操作。(2) CRecordSet 类CRecordSet 类定义了从数据库接收或者发送数据到数据库的成员变量,以实现对数据集的数据操作。CRecordSet 类的成员变量 m_hstmt

10、代表了定义该记录集的 SQL 语句句柄,m_nFields 为记录集中字段的个数,m_nParams 为记录集所使用的参数个数。CRecordSet 的记录集通过 CDatabase 实例的指针实现同数据源的连接,即 CRecordSet 的成员变量 m_pDatabase.MFC ODBC 编程更适合于界面型数据库应用程序的开发,但由于 CDatabase 类和CRecordSet 类提供的数据库操作函数有限,支持的游标类型也有限,限制了高效的数据库开发。在编程层次上属于高级编程。应用实例:1.打开数据库CDatabase database;database.OpenEx( _T( “DSN

11、=zhuxue“ ),CDatabase:noOdbcDialog);/zhuxue 为数据源名称2.关联记录集CRecordset recset(3.查询记录CString sSql1=“;sSql1 = “SELECT * FROM tablename“ ;recset.Open(CRecordset:forwardOnly, sSql1, CRecordset:readOnly);int ti=0;CDBVariant var;/var 可以转换为其他类型的值while (!recset.IsEOF()/读取 Excel 内部数值recset.GetFieldValue(“id“,var

12、);jiangxiangti.id=var.m_iVal;recset.GetFieldValue(“name“, jiangxiangti.name);ti+;recset.MoveNext();recset.Close();/关闭记录集4.执行 sql 语句CString sSql=“;sSql+=“delete * from 院系审核“;/清空表database.ExecuteSQL(sSql);sSql 也可以为 Insert ,Update 等语句5.读取字段名sSql = “SELECT * FROM Sheet1“ ; /读取的文件有 Sheet1 表的定义,或为本程序生成的表.

13、/ 执行查询语句recset.Open(CRecordset:forwardOnly, sSql, CRecordset:readOnly);int excelColCount=recset.GetODBCFieldCount();/列数CString excelfield30;/得到记录集的字段集合中的字段的总个数for( i=0;i数据提供程序数据提供程序拥有自己的数据并把数据以表格的形式呈现给使用者使用.服务提供程序服务提供程序是数据提供程序和使用者的结合。它是 OLE DB 体系结构中的中间件,它是OLE DB 数据源的使用者和数据使用程序的提供者数据使用程序数据使用程序对存储在数据提

14、供程序中的数据进行使用和控制.OLE DB 开发程序的一般步骤:初始化 COM 环境连接数据源打开对话执行命令处理结果清除对象应用实例:使用 OLEDB 编写数据库应用程序1 概述OLE DB 的存在为用户提供了一种统一的方法来访问所有不同种类的数据源。OLE DB 可以在不同的数据源中进行转换。利用 OLE DB,客户端的开发人员在进行数据访问时只需把精力集中在很少的一些细节上,而不必弄懂大量不同数据库的访问协议。OLE DB 是一套通过 COM 接口访问数据的 ActiveX 接口。这个 OLE DB 接口相当通用,足以提供一种访问数据的统一手段,而不管存储数据所使用的方法如何。同时,OL

15、E DB还允许开发人员继续利用基础数据库技术的优点,而不必为了利用这些优点而把数据移出来。2 使用 ATL 使用 OLE DB 数据使用程序由于直接使用 OLE DB 的对象和接口设计数据库应用程序需要书写大量的代码。为了简化程序设计,Visual C+提供了 ATL 模板用于设计 OLE DB 数据应用程序和数据提供程序。利用 ATL 模板可以很容易地将 OLE DB 与 MFC 结合起来,使数据库的参数查询等复杂的编程得到简化。MFC 提供的数据库类使 OLE DB 的编程更具有面向对象的特性。Viual C+所提供用于 OLE DB 的 ATL 模板可分为数据提供程序的模板和数据使用程序

16、的模板。使用 ATL 模板创建数据应用程序一般有以下几步骤:1)创建应用框架2)加入 ATL 产生的模板类3)在应用中使用产生的数据访问对象3 不用 ATL 使用 OLE DB 数据使用程序利用 ATL 模板产生数据使用程序较为简单,但适用性不广,不能动态适应数据库的变化。下面我们介绍直接使用 MFC OLE DB 类来生成数据使用程序。模板的使用OLE DB 数据使用者模板是由一些模板组成的,包括如下一些模板,下面对一些常用类作一些介绍。1)会话类CDataSource 类CDataSource 类与 OLE DB 的数据源对象相对应。这个类代表了 OLE DB 数据提供程序和数据源之间的连

17、接。只有当数据源的连接被建立之后,才能产生会话对象,可以调用 Open来打开数据源的连接。CSession 类CSession 所创建的对象代表了一个单独的数据库访问的会话。一个用 CDataSource 类产生的数据源对象可以创建一个或者多个会话,要在数据源对象上产生一个会话对象,需要调用函数 Open()来打开。同时,会话对象还可用于创建事务操作。CEnumeratorAccessor 类CEnumeratorAccessor 类是用来访问枚举器查询后所产生的行集中可用数据提供程序的信息的访问器,可提供当前可用的数据提供程序和可见的访问器。2)访问器类CAcessor 类CAccessor

18、 类代表与访问器的类型。当用户知道数据库的类型和结构时,可以使用此类。它支持对一个行集采用多个访问器,并且,存放数据的缓冲区是由用户分配的。CDynamicAccessor 类CDynamicAccessor 类用来在程序运行时动态的创建访问器。当系统运行时,可以动态地从行集中获得列的信息,可根据此信息动态地创建访问器。CManualAccessor 类CManualAccessor 类中以在程序运行时将列与变量绑定或者是将参数与变量捆定。3)行集类CRowSet 类CRowSet 类封装了行集对象和相应的接口,并且提供了一些方法用于查询、设置数据等。可以用 Move()等函数进行记录移动,用

19、 GetData()函数读取数据,用 Insert()、Delete()、SetData()来更新数据。CBulkRowset 类CBulkRowset 类用于在一次调用中取回多个行句柄或者对多个行进行操作。CArrayRowset 类CArrayRowset 类提供用数组下标进行数据访问。4)命令类CTable 类CTable 类用于对数据库的简单访问,用数据源的名称得到行集,从而得到数据。CCommand 类CCommand 类用于支持命令的数据源。可以用 Open()函数来执行 SQL 命令,也可以Prepare()函数先对命令进行准备,对于支持命令的数据源,可以提高程序的灵活性和健壮性

20、。在 stdafx.h 头文件里,加入如下代码。#include extern CComModule _Module;#include #include #include / if you are using schema templates在 stdafx.cpp 文件里,加入如下代码。#include CComModule _Module;决定使用何种类型的存取程序和行集。获取数据在打开数据源,会话,行集对象后就可以获取数据了。所获取的数据类型取决于所用的存取程序,可能需要绑定列。按以下步骤。1、用正确的命令打开行集对象。2、如果使用 CManualAccessor,在使用之前与相应列进行

21、绑定。要绑定列,可以用函数GetColumnInfo,如下所示:/ Get the column informationULONG ulColumns = 0;DBCOLUMNINFO* pColumnInfo = NULL;LPOLESTR pStrings = NULL;if (rs.GetColumnInfo(struct MYBIND* pBind = new MYBINDulColumns;rs.CreateAccessor(ulColumns, for (ULONG l=0; l与 ATL 中的 CComPtr类似,是一个在析构时自动调用 Release 的类。 CComPtr的代

22、码在 ATLBASE.H 中定义。2.以下代码均在 UNICODE 环境下编译,因为执行的 SQL 语句必须是 UNICODE 的。设置工程为 UNICODE 的方法是:首先在 project-settings-C/C+的属性页中的 Preprocessor 中,删除_MBCS 写入 UNICODE,_UNICODE。然后在 link 属性页中 Category 中选择 output,在 Entry-Point symbol 中添加 wWinMainCRTStartup。EAutoReleasePtr pIDBInitialize;HRESULT hResult = ConnectDataba

23、se( if( FAILED( hResult ) )/失败,可能是因为数据库没有启动、用户名密码错等等return;EAutoReleasePtr pIOpenRowset;hResult = CreateSession( pIDBInitialize, if( FAILED( hResult ) )/出错return;EAutoReleasePtr pICommand;EAutoReleasePtr pICommandText;hResult = CreateCommand( pIOpenRowset, if( FAILED( hResult ) )/出错return;hResult =

24、ExecuteSQL( pICommand, pICommandText, _T(“USE PBDATA“) );if( FAILED( hResult ) )/如果这里失败,那就是 SQL 语句执行失败。在此处,就是 PBDATA 还未创建return;/ 创建表ExecuteSQL( pICommand, pICommandText, _T(“CREATE TABLE 2005_1(Volume real NOT NULL,ID int NOT NULL IDENTITY)“) );/ 添加记录ExecuteSQL( pICommand, pICommandText, _T(“INSERT

25、 INTO 2005_1 VALUES(100.0)“) );/.其中几个函数的代码如下:HRESULT ConnectDatabase( IDBInitialize* ppIDBInitialize, LPCTSTR pszDataSource, LPCTSTR pszUserID, LPCTSTR pszPassword )ASSERT( ppIDBInitialize != NULL UINT uTimeout 15U; / 连接数据库超时(秒)TCHAR szInitStr1024;VERIFY( 1023 = wsprintf( szInitStr, _T(“Provider=SQL

26、OLEDB;Data Source=%s;Initial Catalog=master;User Id=%s;Password=%s;Connect Timeout=%u“), pszDataSource, pszUserID, pszPassword, uTimeout ) );/Initial Catalog=master 指明连接成功后,“USE master“。EAutoReleasePtr pIDataInitialize;HRESULT hResult = :CoCreateInstance( CLSID_MSDAINITIALIZE, NULL, CLSCTX_INPROC_SE

27、RVER,IID_IDataInitialize, ( void* )if( FAILED( hResult ) )return hResult;EAutoReleasePtr pIDBInitialize;hResult = pIDataInitialize-GetDataSource( NULL, CLSCTX_INPROC_SERVER, ( LPCOLESTR )szInitStr,IID_IDBInitialize, ( IUnknown* )if( FAILED( hResult ) )return hResult;hResult = pIDBInitialize-Initiali

28、ze( );if( FAILED( hResult ) )return hResult;* ppIDBInitialize = pIDBInitialize.Detach( );return S_OK;HRESULT CreateSession( IDBInitialize* pIDBInitialize, IOpenRowset* ppIOpenRowset )ASSERT( pIDBInitialize != NULL EAutoReleasePtr pSession;HRESULT hResult = pIDBInitialize-QueryInterface( IID_IDBCreat

29、eSession, ( void* )if( FAILED( hResult ) )return hResult;EAutoReleasePtr pIOpenRowset;hResult = pSession-CreateSession( NULL, IID_IOpenRowset, ( IUnknown* )if( FAILED( hResult ) )return hResult;* ppIOpenRowset = pIOpenRowset.Detach( );return S_OK;HRESULT CreateCommand( IOpenRowset* pIOpenRowset, ICo

30、mmand* ppICommand, ICommandText* ppICommandText )ASSERT( pIOpenRowset != NULL HRESULT hResult;EAutoReleasePtr pICommand;EAutoReleasePtr pICreateCommand;hResult = pIOpenRowset-QueryInterface( IID_IDBCreateCommand, ( void* )if( FAILED( hResult ) )return hResult;hResult = pICreateCommand-CreateCommand(

31、 NULL, IID_ICommand, (IUnknown*)if( FAILED( hResult ) )return hResult;EAutoReleasePtr pICommandText;hResult = pICommand-QueryInterface( if( FAILED( hResult ) )return hResult;* ppICommand = pICommand.Detach( );* ppICommandText = pICommandText.Detach( );return S_OK;HRESULT ExecuteSQL( ICommand* pIComm

32、and, ICommandText* pICommandText, LPCTSTR pszCommand, LONG* plRowsAffected )ASSERT( pICommand != NULL HRESULT hResult = pICommandText-SetCommandText( DBGUID_DBSQL, ( LPCOLESTR )pszCommand );if( FAILED( hResult ) )return hResult;LONG lAffected;hResult = pICommand-Execute( NULL, IID_NULL, NULL, plRows

33、Affected = NULL ? return hResult;以上就是写数据库的全部代码了,是不是很简单呢?下面再来读的。/ 先用与上面代码中一样的步骤获取 pICommand,pICommandText。此处省略HRESULT hResult = pICommandText-SetCommandText( DBGUID_DBSQL, ( LPCOLESTR )_T(“SELECT Volume FROM 2005_1 WHERE ID = IDENTITY“) ); /取我们刚刚添加的那一条记录if( FAILED( hResult ) )return;LONG lAffected;EA

34、utoReleasePtr pIRowset;hResult = pICommand-Execute( NULL, IID_IRowset, NULL, if( FAILED( hResult ) )return;EAutoReleasePtr pIAccessor;hResult = pIRowset-QueryInterface( IID_IAccessor, ( void* )if( FAILED( hResult ) )return;/ 一个根据表中各字段的数值类型而定义的结构,用于存储返回的各字段的值struct CLoadLastFromDBDBSTATUS dwdsVolume;

35、DWORD dwLenVolume;float fVolume;/ 此处我们只查询了一个字段。如果要查询多个字段,CLoadLastFromDB 中要添加相应的字段定义,下面的 dbBinding 也要相应扩充。dbBinding.iOrdinal 要分别指向各个字段,dbBinding.wType 要根据字段类型赋合适的值。DBBINDING dbBinding1;dbBinding0.iOrdinal = 1; / Volume 字段的位置,从 1 开始dbBinding0.obValue = offsetof( CLoadLastFromDB, fVolume );dbBinding0.

36、obLength = offsetof( CLoadLastFromDB, dwLenVolume );dbBinding0.obStatus = offsetof( CLoadLastFromDB, dwdsVolume );dbBinding0.pTypeInfo = NULL;dbBinding0.pObject = NULL;dbBinding0.pBindExt = NULL;dbBinding0.dwPart = DBPART_VALUE | DBPART_STATUS | DBPART_LENGTH;dbBinding0.dwMemOwner = DBMEMOWNER_CLIEN

37、TOWNED;dbBinding0.eParamIO = DBPARAMIO_NOTPARAM;dbBinding0.cbMaxLen = 0;dbBinding0.dwFlags = 0;dbBinding0.wType = DBTYPE_R4; / float 就是 DBTYPE_R4,int 就是 DBTYPE_I4。参见 MSDNdbBinding0.bPrecision = 0;dbBinding0.bScale = 0;HACCESSOR hAccessor = DB_NULL_HACCESSOR;DBBINDSTATUS dbs1;hResult = pIAccessor-Cre

38、ateAccessor( DBACCESSOR_ROWDATA, 1, dbBinding, sizeof( CLoadLastDataFromDB ), if( FAILED( hResult ) )return;ASSERT( dbs0 = DBBINDSTATUS_OK );ULONG uRowsObtained = 0;HROW hRows1; / 这里我们只查询了最新的那一条记录HROW* phRows = hRows;CLoadLastFromDB rmd;hResult = pIRowset-GetNextRows( NULL, 0, 1, if( SUCCEEDED( hRes

39、ult ) if( FAILED( hResult ) )ASSERT( FALSE );ASSERT( rmd.dwdsVolume = DBSTATUS_S_OK );/ rmd.fVolume 就是我们要取的值pIRowset-ReleaseRows( uRowsObtained, phRows, NULL, NULL, NULL );pIAccessor-ReleaseAccessor( hAccessor, NULL );pIAccessor.Release( );pIRowset.Release( );读操作也完成了,是不是仍然很简单呢?下面我们再来看看最麻烦的二进制数据(text

40、 、 ntext、 image 等)的读写。要实现 BLOB 数据的读写,我们需要一个辅助的类,定义如下:class CSequentialStream : public ISequentialStream / BLOB 数据访问类public:CSequentialStream( );virtual CSequentialStream( );virtual BOOL Seek( ULONG uPosition );virtual BOOL Clear( );virtual ULONG GetLength( ) return m_uBufferUsed; ;virtual operator v

41、oid* const( ) return m_pBuffer; ;STDMETHODIMP_( ULONG ) AddRef( ) return + m_uRefCount; ;STDMETHODIMP_( ULONG ) Release( ) ASSERT( m_uRefCount != 0U );- m_uRefCount;if( m_uRefCount = 0U ) delete this; return m_uRefCount; ;STDMETHODIMP QueryInterface( REFIID riid, LPVOID* ppv );STDMETHODIMP Read( voi

42、d _RPC_FAR* pv, ULONG cb, ULONG _RPC_FAR* pcbRead );STDMETHODIMP Write( const void _RPC_FAR* pv, ULONG cb, ULONG _RPC_FAR* pcbWritten );void ResetPosition( ) m_uPosition = 0U; ;HRESULT PreAllocBuffer( ULONG uSize );private:ULONG m_uRefCount; / reference countvoid* m_pBuffer; / bufferULONG m_uBufferU

43、sed; / buffer usedULONG m_uBufferSize; / buffer sizeULONG m_uPosition; / current index position in the buffer;实现如下:CSequentialStream:CSequentialStream( ) : m_uRefCount( 0U ), m_pBuffer( NULL ), m_uBufferUsed( 0U ), m_uBufferSize( 0U ), m_uPosition( 0U )AddRef( );CSequentialStream:CSequentialStream(

44、)Clear( );HRESULT CSequentialStream:QueryInterface( REFIID riid, void* ppv )if( riid = IID_IUnknown | riid = IID_ISequentialStream )* ppv = this;( ( IUnknown* )*ppv )-AddRef( );return S_OK;* ppv = NULL;return E_NOINTERFACE;BOOL CSequentialStream:Seek( ULONG uPosition )ASSERT( uPosition uBytesLeft ?

45、uBytesLeft : cb );memcpy( pv, ( BYTE* )m_pBuffer + m_uPosition, uBytesRead );m_uPosition += uBytesRead;( pcbRead != NULL ? ( * pcbRead = uBytesRead ) : 0 );return ( cb != uBytesRead ? S_FALSE : S_OK );HRESULT CSequentialStream:Write( const void* pv, ULONG cb, ULONG* pcbWritten )if( pv = NULL ) retur

46、n STG_E_INVALIDPOINTER; ( pcbWritten != NULL ? ( * pcbWritten = 0U ) : 0 );if( cb = 0U ) return S_OK; ASSERT( m_uPosition pICommandProperties;hResult = pICommandText-QueryInterface( IID_ICommandProperties, ( void* )/ 设置 Rowset 属性为“可以更新某字段的值”hResult = pICommandProperties-SetProperties( 1, hResult = p

47、ICommandText-SetCommandText( DBGUID_DBSQL, ( LPCOLESTR )L“SELECT Contents FROM News WHERE ID = IDENTITY“ );LONG lAffected;EAutoReleasePtr pIRowsetChange;hResult = pICommand-Execute( NULL, IID_IRowsetChange, NULL, EAutoReleasePtr pIAccessor;hResult = pIRowsetChange-QueryInterface( IID_IAccessor, ( vo

48、id* )struct BLOBDATADBSTATUS dwStatus;DWORD dwLength;ISequentialStream* pISeqStream;/ 有关 DBOBJECT、DBBINDING 的设置,建议参考 MSDN,很容易懂。DBOBJECT dbObj;dbObj.dwFlags = STGM_READ;dbObj.iid = IID_ISequentialStream;DBBINDING dbBinding;dbBinding.iOrdinal = 1; / BLOB 字段的位置,从 1 开始dbBinding.obValue = offsetof( BLOBD

49、ATA, pISeqStream );dbBinding.obLength = offsetof( BLOBDATA, dwLength );dbBinding.obStatus = offsetof( BLOBDATA, dwStatus );dbBinding.pTypeInfo = NULL;dbBinding.pObject = dbBinding.pBindExt = NULL;dbBinding.dwPart = DBPART_VALUE | DBPART_STATUS | DBPART_LENGTH;dbBinding.dwMemOwner = DBMEMOWNER_CLIENTOWNED;dbBinding.eParam

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报