zoukankan      html  css  js  c++  java
  • ADO中记录集recordSet的使用

    _RecordsetPtr使用方法

    _variant_t vUsername,vID,vname; //变量声明
    _RecordsetPtr m_pRecordset;     //记录集
    CString strid;
    _ConnectionPtr connection;
    m_pRecordset.CreateInstance(__uuidof( Recordset )); //创建实例
    m_pRecordset->Open("SELECT * FROM users",connection.GetInterfacePtr

    (),adOpenStatic,adLockOptimistic,adCmdText);//执行SQL语句,得到记录集, connection必须已和数

    据库连接

    /*************原型*****************/
    Open方法的原型是这样的:
    HRESULT Recordset15::Open ( const _variant_t & Source, const _variant_t & ActiveConnection,

    enum CursorTypeEnum CursorType, enum LockTypeEnum LockType, long Options )

    /***********************************/


    /************************************************/
    ①Source是数据查询字符串
    ②ActiveConnection是已经建立好的连接(我们需要用Connection对象指针来构造一个_variant_t对象) 
    ③CursorType光标类型,它可以是以下值之一,请看这个枚举结构:
    enum CursorTypeEnum
    {
    adOpenUnspecified = -1,///不作特别指定
    adOpenForwardOnly = 0,///前滚静态光标。这种光标只能向前浏览记录集,比如用MoveNext向前滚动,这

    种方式可以提高浏览速度。但诸如BookMark,RecordCount,AbsolutePosition,AbsolutePage都不能使用
    adOpenKeyset = 1,///采用这种光标的记录集看不到其它用户的新增、删除操作,但对于更新原有记录的

    操作对你是可见的。
    adOpenDynamic = 2,///动态光标。所有数据库的操作都会立即在各用户记录集上反应出来。
    adOpenStatic = 3///静态光标。它为你的记录集产生一个静态备份,但其它用户的新增、删除、更新操

    作对你的记录集来说是不可见的。
    };
    ④LockType锁定类型,它可以是以下值之一,请看如下枚举结构:
    enum LockTypeEnum
    {
    adLockUnspecified = -1,///未指定
    adLockReadOnly = 1,///只读记录集
    adLockPessimistic = 2,悲观锁定方式。数据在更新时锁定其它所有动作,这是最安全的锁定机制
    adLockOptimistic = 3,乐观锁定方式。只有在你调用Update方法时才锁定记录。在此之前仍然可以做数

    据的更新、插入、删除等动作
    adLockBatchOptimistic = 4,乐观分批更新。编辑时记录不会锁定,更改、插入及删除是在批处理模式

    下完成。
    };
    5.option可以取以下值 
    adCmdText:表明CommandText是文本命令
    adCmdTable:表明CommandText是一个表名
    adCmdProc:表明CommandText是一个存储过程
    adCmdUnknown:未知

    /******************************************************/

    while(!m_pRecordset->adoEOF)///这里为什么是adoEOF而不是EOF呢?还记得rename("EOF","adoEOF")这

    一句吗?
    {
    vID = m_pRecordset->GetFields()->GetItem((long)0).Value;///取得第1列的值,从0开始计数,
    strid = (TCHAR*)(_bstr_t)vID //转换为字符串

    vname = m_pRecordset->GetFields()->GetItem( (long)0).name;//取得第一列属性名
    //以直接给出列的名称,如下一行
    vUsername = m_pRecordset->GetCollect("username");///取得username字段的值

    m_pRecordset->MoveNext();///移到下一条记录
    }
    m_pRecordset->GetFields()->Count//获得一条记录的字段数

    m_pRecordset->MoveFirst();///移到首条记录

    m_pRecordset->Delete(adAffectCurrent);///删除当前记录
    ///添加三条新记录并赋值
    for(int i=0;i<3;i++)
    {
    m_pRecordset->AddNew();///添加新记录
    m_pRecordset->PutCollect("ID",_variant_t((long)(i+10)));
    m_pRecordset->PutCollect("username",_variant_t("haiyan"));
    m_pRecordset->PutCollect("old",_variant_t((long)71));
    m_pRecordset->PutCollect("birthday",_variant_t("1930-3-15"));
    }
    m_pRecordset->Move(1,_variant_t((long)adBookmarkFirst));///从第一条记录往下移动一条记录,即移

    动到第二条记录处
    m_pRecordset->PutCollect(_variant_t("old"),_variant_t((long)45));///修改其年龄
    m_pRecordset->Update();///保存到库中

    在这说明一下:

    在我的一个.NET数据库连接程序中,出现一个问题,每次初始化打开数据集时程序报错说"数据库打开错误,无效指针",让我郁闷好几个小时,后来发现,当我在创建数据库连接对象前加入函数CoInitialize(NULL)后,错误解决,源码如下:

    CoInitialize(NULL);
    hr=m_pConnection.CreateInstance(_uuidof(Connection));

    MSDC说明如下:

    You need to initialize the COM library on an apartment before you call any of the

    library functions except CoGetMalloc,to get a pointer to the standard allocator,

    and the memory allocation functions

    (转)

    为了取得结果记录集,我们定义一个指向Recordset对象的指针:_RecordsetPtr m_pRecordset; 
    并为其创建Recordset对象的实例: m_pRecordset.CreateInstance("ADODB.Recordset"); 
    SQL命令的执行可以采用多种形式,下面我们一进行阐述。 

    (1)利用Connection对象的Execute方法执行SQL命令 
    Execute方法的原型如下所示: 
    _RecordsetPtr Connection15::Execute ( _bstr_t CommandText, VARIANT * RecordsAffected, long Options ) 其中CommandText是命令字串,通常是SQL命令。参数RecordsAffected是操作完成后所影响的行数, 参数Options表示CommandText中内容的类型,Options可以取如下值之一: 
    adCmdText:表明CommandText是文本命令 
    adCmdTable:表明CommandText是一个表名 
    adCmdProc:表明CommandText是一个存储过程 
    adCmdUnknown:未知 

    Execute执行完后返回一个指向记录集的指针,下面我们给出具体代码并作说明。 _variant_t RecordsAffected; 
    ///执行SQL命令:CREATE TABLE创建表格users,users包含四个字段:整形ID,字符串username,整形old,日期型birthday 
    m_pConnection->Execute("CREATE TABLE users(ID INTEGER,username TEXT,old INTEGER,birthday DATETIME)",&RecordsAffected,adCmdText); 
    ///往表格里面添加记录 
    m_pConnection->Execute("INSERT INTO users(ID,username,old,birthday) valueS (1, nullnullnullnullnullnullnullnullWashingtonnullnullnullnullnullnullnullnull,25,nullnullnullnullnullnullnullnull1970/1/1nullnullnullnullnullnullnullnull)",&RecordsAffected,adCmdText);
    ///将所有记录old字段的值加一 
    m_pConnection->Execute("UPDATE users SET old = old+1",&RecordsAffected,adCmdText); 
    ///执行SQL统计命令得到包含记录条数的记录集 
    m_pRecordset = m_pConnection->Execute("SELECT COUNT(*) FROM users",&RecordsAffected,adCmdText); 
    _variant_t vIndex = (long)0; 
    _variant_t vCount = m_pRecordset->GetCollect(vIndex);///取得第一个字段的值放入vCount变量 
    m_pRecordset->Close();///关闭记录集 
    CString message; 
    message.Format("共有%d条记录",vCount.lVal); 
    AfxMessageBox(message);///显示当前记录条数 


    (2)利用Command对象来执行SQL命令 
    _CommandPtr m_pCommand; 
    m_pCommand.CreateInstance("ADODB.Command"); 
    _variant_t vNULL; 
    vNULL.vt = VT_ERROR; 
    vNULL.scode = DISP_E_PARAMNOTFOUND;///定义为无参数 
    m_pCommand->ActiveConnection = m_pConnection;///非常关键的一句,将建立的连接赋值给它 
    m_pCommand->CommandText = "SELECT * FROM users";///命令字串 
    m_pRecordset = m_pCommand->Execute(&vNULL,&vNULL,adCmdText);///执行命令,取得记录集 

    在这段代码中我们只是用Command对象来执行了SELECT查询语句,Command对象在进行存储过程的调用中能真正体现它的作用。下次我们将详细介

    _RecordsetPtr

    _RecordsetPtr智能指针,它是专门为通过记录集操作数据库而设立的指针,通过该接口可以对数据库的表内的记录、字段等进行各种操作。

    要搞清楚:数据库和ADO的记录集是两个不同的概念, 是存在于不同物理位置的两个存储空间。 记录集相当于是实际数据的一份拷贝。 正因为记录集是相对脱离数据库而存在的, 所以才存在后面将要介绍的Open方法中涉及的光标类型和锁定类型这两个问题。

    _RecordsetPtr接口的使用方法:

    先创建记录集对象:

    _ConnectionPtr m_pRecordset;

    m_pRecordset.CreateInstance(__uuidof(Recorset));

    创建记录集对象后,只是为它分配内存空间,记录集中不含任何数据。记录集对象是用来获得数据库中的数据并对其操作的,所以还要打开记录集,从数据库中取得数据记录。可有多种方法打开记录集,下面只介绍最常用的Open方法:

    为记录集对象分配了空间后就可以用Open函数打开记录集,该函数原型为:

    HRESULT Recordset15::Open(const _variant_t& Source,const _variant_t& ActiveConnection,enum CursorTypeEnum CursorType,enum LockTypeEnum LockType,long Options)

    参数:

    Source是数据查询字符串。

    ActiveConnection是已经建立好的连接(我们需要用Connection对象指针来构造一个_variant_t对象)。

    CursorType 光标类型,它是枚举CursorTypeEnum中的一个值。

    LockType 锁定类型 它是枚举LockTypeEnum中的一个值

    Options 指定Source的类型

    光标类型CursorType,可取如下值之一:

    adOpenUnspecified=-1 不作特别指定

    adOpenForwardOnly=0 默认值,前滚静态光标。这种光标只能向前浏览记录集,比如用MoveNext向前滚动,这种方式可节省资源,提高浏览速度,但诸如BookMark、RecordCount、AbsolutePosition、AbsolutePage都不能使用。

    adOpenKeyset=1 键集游标,采用这种光标的记录集看不到其它用户的新增、删除操作,但对于更新原有记录的操作对你是可见的。

    adOpenDynamic=2 动态光标,所有数据库的操作都会立即在用户记录集上反应出来。

    adOpenStatic=3 静态游标。它为记录产生一个静态备份,其他用户的新增、删除、更新操作对你的记录集来说是不可见的。

    LockType锁定类型,它可以是以下值之一,请看如下枚举结构

    enum LockTypeEnum

    {

    adLockUnspecified=-1,

    //未指定

    adLockReadOnly=1,

    //只读记录集,默认值。无法更改数据。

    adLockPessimistic=2,

    //悲观锁定方式。只有在调用Update方法时才锁定记录。这是最安全的锁定机制

    adLockOptimistc=3,

    //乐观锁定方式,只有在你调用Update方法时才锁定记录。

    在此之前仍然可以做数据的更新、插入、删除等操作

    adLockBatchOptimistic=4 乐观分批更新。编辑时记录不会锁定,更改、插入及删除是在批处理模式下完成。

    }

    关于光标和锁定类型,对于一般用户,建议您只作简单了解,后面将进一步进行解说。

    Options可以取如下值之一:

    adCmdText: 表明CommandText是文本命令。

    adCmdTable:表明CommandText是一个表名。

    adCmdProc:表明CommandText是一个存储过程。

    adCmdUnknown:未知。

    例如:假设m_pConnection是我们已经建立好的连接,我们使用_RecordsetPtr接口的Open方法打开Employees表的记录集的语句如下:

    m_pRecordset->Open(“SELECT * FROM Employees”,

    _variant_t((IDispatch*)m_pConnection,true),

    adOpenStatic,

    adLockOptimistic,

    adCmdText);

    例程RecordsetPtr演示使用_RecordsetPtr指针通过记录集操作数据库。

    打开VC++ 6.0,新建一个基于对话框的工程RecordsetPtr。在对话框IDD_RECORDSETPTR_DIALOG中进行编辑:

    使用三个Group Box分成四个部分,第一部分演示如何读取数据库数据;第二部分演示如何修改数据库;第三部分演示如何向数据库中插入数据;第四部分演示如何删除数据库中的数据。

    使用ClassWizard给列表框IDC_LIST1创建CListBox变量m_list1:

    双击IDC_BTN_READREC按钮,并编辑OnBtnReadrec()函数如下:

    void CRecordsetPtrDlg::OnBtnReadrec()

    {

    _ConnectionPtr m_pConnection;

    _RecordsetPtr m_pRecordset;

    try

    {

    m_pConnection.CreateInstance(__uuidof(Connection));

    m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Northwind.mdb","","",adModeUnknown);

    }

    catch(_com_error e)

    {

    CString errormessage;

    errormessage.Format("连接数据库失败!/r错误信息:%s",e.ErrorMessage());

    AfxMessageBox(errormessage);

    return;

    }

    try

    {

    m_pRecordset.CreateInstance("ADODB.Recordset");

    m_pRecordset->Open("SELECT EmployeeID,FirstName,LastName,HireDate,City FROM Employees WHERE City='London'",

    _variant_t((IDispatch*)m_pConnection,true),

    adOpenStatic,

    adLockOptimistic,

    adCmdText);

    }

    catch(_com_error &e)

    {

    AfxMessageBox(e.Description());

    }

    _variant_t vEmployeeID,vFirstName,vLastName,vHireDate,vCity;

    try

    {

    while(!m_pRecordset->adoEOF)

    {

    vEmployeeID=m_pRecordset->GetCollect(_variant_t((long)0));

    //取得第1列的值,从0开始计数,你也可以直接列出列的名称,如下一行

    vFirstName=m_pRecordset->GetCollect("FirstName");

    vLastName=m_pRecordset->GetCollect("LastName");

    vHireDate=m_pRecordset->GetCollect("HireDate");

    vCity=m_pRecordset->GetCollect("City");

    CString strtemp;

    if(vEmployeeID.vt!=VT_NULL)

    {

    strtemp.Format("%d",vEmployeeID.lVal);

    }

    if(vFirstName.vt!=VT_NULL)

    {

    strtemp+=" ";

    strtemp+=(LPCTSTR)(_bstr_t)vFirstName;

    }

    if(vLastName.vt!=VT_NULL)

    {

    strtemp+=" ";

    strtemp+=(LPCTSTR)(_bstr_t)vLastName;

    }

    if(vHireDate.vt!=VT_NULL)

    {

    strtemp+=" ";

    strtemp+=(LPCTSTR)(_bstr_t)vHireDate;

    }

    if(vCity.vt!=VT_NULL)

    {

    strtemp+=" ";

    strtemp+=(LPCTSTR)(_bstr_t)vCity;

    }

    m_list1.AddString(strtemp);

    m_list1.AddString("/n");

    m_pRecordset->MoveNext();

    }

    }

    catch(_com_error &e)

    {

    AfxMessageBox(e.Description());

    }

    m_pRecordset->Close();

    m_pRecordset=NULL;

    m_pConnection->Close();

    m_pConnection=NULL;

    }

    该段代码演示了如何读取数据库表内的数据。其原理是如果没有遇到表结束标志adoEOF,则用GetCollect(字段名)来获取当前记录指针所指的字段值,然后再用MoveNext()方法移动到下一条记录位置。

    双击IDC_BTN_CHANGE按钮,并编辑OnBtnChange()函数如下:

    void CRecordsetPtrDlg::OnBtnChange()

    {

    _ConnectionPtr m_pConnection;

    _RecordsetPtr m_pRecordset;

    try

    {

    m_pConnection.CreateInstance(__uuidof(Connection));

    m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Northwind.mdb","","",adModeUnknown);

    }

    catch(_com_error e)

    {

    CString errormessage;

    errormessage.Format("连接数据库失败!/r错误信息:%s",e.ErrorMessage());

    AfxMessageBox(errormessage);

    return;

    }

    try

    {

    m_pRecordset.CreateInstance("ADODB.Recordset");

    m_pRecordset->Open("SELECT EmployeeID,FirstName,LastName,HireDate,City FROM Employees WHERE (City='London') AND (EmployeeID=6)",

    _variant_t((IDispatch*)m_pConnection,true),

    adOpenStatic,

    adLockOptimistic,

    adCmdText);

    }

    catch(_com_error &e)

    {

    AfxMessageBox(e.Description());

    }

    try

    {

    while(!m_pRecordset->adoEOF)

    {

    m_pRecordset->PutCollect("LastName",_variant_t("Jackson"));

    m_pRecordset->MoveNext();

    }

    m_pRecordset->Update();

    }

    catch(_com_error* e)

    {

    AfxMessageBox(e->ErrorMessage());

    }

    m_pRecordset->Close();

    m_pRecordset=NULL;

    m_pConnection->Close();

    m_pConnection=NULL;

    }

    该段代码演示了如何修改记录中的字段值:

    将记录指针移动到要修改记录的位置处,直接用PutCollect(字段名,值)将新值写入并Update()更新到数据库即可。

    移动记录指针可以通过MoveFirst()方法移动到第一条记录,MoveLast()方法移动到最后一条记录,MovePrevious()方法移动到当前记录的前一条记录,MoveNext()方法移动到当前记录的下一条记录。也可以使用Move(记录号)移动记录指针到需要位置。注意:Move()方法是相对于当前记录来移动指针位置的。正值向后移动,负值向前移动。如Move(3),当前记录是3时,它将从记录3开始往后再移动3条记录位置。关于移动记录指针后面将会用到。

    双击IDC_BTN_NEW按钮,并编辑OnBtnNew()函数如下:

    void CRecordsetPtrDlg::OnBtnNew()

    {

    _ConnectionPtr m_pConnection;

    _RecordsetPtr m_pRecordset;

    try

    {

    m_pConnection.CreateInstance(__uuidof(Connection));

    m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Northwind.mdb","","",adModeUnknown);

    }

    catch(_com_error e)

    {

    CString errormessage;

    errormessage.Format("连接数据库失败!/r错误信息:%s",e.ErrorMessage());

    AfxMessageBox(errormessage);

    return;

    }

    try

    {

    m_pRecordset.CreateInstance("ADODB.Recordset");

    m_pRecordset->Open("SELECT * FROM Employees",

    _variant_t((IDispatch*)m_pConnection,true),

    adOpenStatic,

    adLockOptimistic,

    adCmdText);

    }

    catch(_com_error &e)

    {

    AfxMessageBox(e.Description());

    }

    try

    {

    m_pRecordset->MoveLast();

    m_pRecordset->AddNew();

    m_pRecordset->PutCollect("EmployeeID",_variant_t((long)10));

    m_pRecordset->PutCollect("FirstName",_variant_t("Mary"));

    m_pRecordset->PutCollect("LastName",_variant_t("Williams"));

    m_pRecordset->PutCollect("HireDate",_variant_t("15/4/1993 12:00:00"));

    m_pRecordset->PutCollect("City",_variant_t("New York"));

    m_pRecordset->PutCollect("Country",_variant_t("USA"));

    }

    catch(_com_error *e)

    {

    AfxMessageBox(e->ErrorMessage());

    }

    m_pRecordset->Update();

    m_pRecordset->Close();

    m_pRecordset=NULL;

    m_pConnection->Close();

    m_pConnection=NULL;

    }

    该段代码演示如何插入记录:

    先用AddNew()方法新增一个空记录,再用PutCollect(字段名,值)输入每个字段的值,最后用Update()更新到数据库即可。

    双击IDC_BTN_DELETE按钮,并编辑OnBtnDelete()函数如下:

    void CRecordsetPtrDlg::OnBtnDelete()

    {

    _ConnectionPtr m_pConnection;

    _RecordsetPtr m_pRecordset;

    try

    {

    m_pConnection.CreateInstance(__uuidof(Connection));

    m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Northwind.mdb","","",adModeUnknown);

    }

    catch(_com_error e)

    {

    CString errormessage;

    errormessage.Format("连接数据库失败!/r错误信息:%s",e.ErrorMessage());

    AfxMessageBox(errormessage);

    return;

    }

    try

    {

    m_pRecordset.CreateInstance("ADODB.Recordset");

    m_pRecordset->Open("SELECT * FROM Employees",

    _variant_t((IDispatch*)m_pConnection,true),

    adOpenStatic,

    adLockOptimistic,

    adCmdText);

    }

    catch(_com_error &e)

    {

    AfxMessageBox(e.Description());

    }

    try

    {

    //假设删除第10条记录

    m_pRecordset->MoveFirst();

    m_pRecordset->Move(9);

    m_pRecordset->Delete(adAffectCurrent);

    //参数adAffectCurrent为删除当前记录

    m_pRecordset->Update();

    }

    catch(_com_error *e)

    {

    AfxMessageBox(e->ErrorMessage());

    }

    m_pRecordset->Close();

    m_pRecordset=NULL;

    m_pConnection->Close();

    m_pConnection=NULL;

    }

    该段代码演示了如何删除记录:

    先将记录指针移动到要删除的记录的位置,直接用Delete()方法删除它,并用Update()来更新数据库即可。

    使用记录集操作完毕后要关闭记录集:

    直接用Close()方法关闭记录集并赋予其空值。代码如下:

    m_pRecordset->Close();

    m_pConnection->Close();

    m_pRecordset=NULL;

    m_pConnection=NULL;

  • 相关阅读:
    python关于字符串数据类型的方法
    python流程控制
    python解释器下载
    (转)蓝牙无线技术配置文件
    Android 编译选项user、userdebug和eng的区别
    (转)android4.0蓝牙使能的详细解析
    (转)Android Bluetooth opp package 学习笔记
    《深入理解Android(卷1)》笔记 1.第二章 深入理解JNI
    (转)Vim知识
    Android之Preference
  • 原文地址:https://www.cnblogs.com/fickleness/p/3149016.html
Copyright © 2011-2022 走看看