热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何用CRecordSet类进行多次数据库操作,Open后再查询怎么办?

某处看到的:“使用过CRecordSet::Open()函数,再次查询时就可以应用CRecordSet::Requery()函数。CRecordSet类对象的初始化,缺省数据源由GetDefaul
某处看到的:“使用过CRecordSet::Open()函数,再次查询时就可以应用CRecordSet::Requery() 函数。CRecordSet 类对象的初始化,缺省数据源由GetDefaultConnect()函数获得,
!!也可以提供你所需要的SQL 语句,并以它来调用CRecordSet::Open() 函数!!(就是不明白自定义的语句可用于多次查询么?我做的时候怎么出错了?)
查询过程中也可以利用CRecordSet 的成员变量m_strFilter 和m_strSort 来执行条件查询和结果排序。”

 CPersonSet m_recordset(&m_database);
    CString searchid;
    searchid.Format("ID=%d",i);
    strSQL.Format("select * from person where %s",searchid);

    //初始查询操作--》
    m_recordset.m_strFilter=searchid;//利用成员变量来操作的(A)两句
    m_recordset.Open(AFX_DB_USE_DEFAULT_TYPE,NULL);

    //m_recordset.Open(AFX_DB_USE_DEFAULT_TYPE,strSQL);//××××利用自定义sql语句来操作的语句(B)

    m_recordset.m_strFilter="NAME='vfcgf'";
    //不关闭m_recordset做连续的第2次查询,
    m_recordset.Requery();
    AfxMessageBox("requery success");

问题1:
用A处的代码没有问题,但是A换成B的话Requery();就出错“语法错误(操作符丢失)在查询表达式‘ID=1 WHERE NAME=‘vfcgf’’中”,为什么换了后的效果是这样呢?

问题2:
我是用CLASS WIZARD添加的CRecordset继承类,关联数据源时选择的是snapshot,
我在程序里这样m_recordset->Open(CRecordset::dynaset,str_SQL,CRecordset::readOnly);
会提示我说提示说:“ODBC驱动程序不支持动态记录集”
这又是为什么呢?我访问的是ACCESS数据源。
我又用class wizard里UpdateColumon更新程序里的CPersonSet的设置,选dynaset的RADIO钮,可是点确定关闭class wizard后再ctrl+w,再操作一下看却仍是snapshot被选中,我到CPersonSet代码里把type的参数改成dynaset。可是还是那个提示,郁闷。。。

12 个解决方案

#1



strSQL.Format("select * from person where %s",searchid);
//这个SQL语句明显有问题,你查询的条件列在哪里呢?

2
m_recordset->Open(CRecordset::dynaset,str_SQL,CRecordset::dynaset);

#2


virtual BOOL Open(
   UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE,
   LPCTSTR lpszSQL = NULL,
   DWORD dwOptions = none 
);
Parameters
nOpenType 
Accept the default value, AFX_DB_USE_DEFAULT_TYPE, or use one of the following values from the enum OpenType: 
CRecordset::dynaset   A recordset with bi-directional scrolling. The membership and ordering of the records are determined when the recordset is opened, but changes made by other users to the data values are visible following a fetch operation. Dynasets are also known as keyset-driven recordsets. 
CRecordset::snapshot   A static recordset with bi-directional scrolling. The membership and ordering of the records are determined when the recordset is opened; the data values are determined when the records are fetched. Changes made by other users are not visible until the recordset is closed and then reopened. 
CRecordset::dynamic   A recordset with bi-directional scrolling. Changes made by other users to the membership, ordering, and data values are visible following a fetch operation. Note that many ODBC drivers do not support this type of recordset. 
CRecordset::forwardOnly


试试把AFX_DB_USE_DEFAULT_TYPE改为CRecordset::dynaset或CRecordset::snapshot

#3


你的requery()函数用的不对。
参考以下文章:
3.22 查询记录

查询记录使用CRecordSet::Open()和 CRecordSet::Requery()成员函数。在使用CRecordSet类对象之前,必须使用 CRecordSet::Open()函数来获得有效的记录集。一旦已经使用过CRecordSet::Open() 函数,再次查询时就可以应用CRecordSet::Requery()函数。在调 用CRecordSet::Open()函数时,如果已经将一个已经打开的CDatabase 对象指针传给CRecordSet类对象的m_pDatabase成员变量,则使 用该数据库对象建立ODBC连接;否则如果m_pDatabase为空指 针,就新建一个CDatabase类对象并使其与缺省的数据源 相连,然后进行CRecordSet类对象的初始化。缺省数据源 由GetDefaultConnect()函数获得。你也可以提供你所需要的SQL 语句,并以它来调用CRecordSet::Open()函数,例如:

m_Set.Open(AFX_DATABASE_USE_DEFAULT,strSQL);

如果没有指定参数,程序则使 用缺省的SQL语句,即对在GetDefaultSQL()函数中指定的SQL语 句进行操作: 

CString CTestRecordSet::GetDefaultSQL()

{return _T("[BasicData],[MainSize]");}

对于GetDefaultSQL()函数返回的表名, 对应的缺省操作是SELECT语句,即:

SELECT * FROM BasicData,MainSize 
 

查询过程中也可以利用CRecordSet的 成员变量m_strFilter和m_strSort来执行条件查询和结果排序。m_strFilter 为过滤字符串,存放着SQL语句中WHERE后的条件串;m_strSort 为排序字符串,存放着SQL语句中ORDERBY后的字符串。 如:

m_Set.m_strFilter="TYPE='电动机'";

m_Set.m_strSort="VOLTAGE";

m_Set.Requery();

对应的SQL语句为:

SELECT * FROM BasicData,MainSize 

WHERE TYPE='电动机'

ORDER BY VOLTAGE
 

除了直接赋值给m_strFilter以外,还 可以使用参数化。利用参数化可以更直观,更方便地 完成条件查询任务。使用参数化的步骤如下: 

(1).声明参变量: 

Cstring p1;

Float p2;

(2).在构造函数中初始化参变量

p1=_T("");

p2=0.0f;

m_nParams=2;

(3).将参变量与对应列绑定

pFX->SetFieldType(CFieldExchange::param)

RFX_Text(pFX,_T("P1"),p1);

RFX_Single(pFX,_T("P2"),p2);

完成以上步骤之后就可以利用参变量进行条件查询了:

m_pSet->m_strFilter="TYPE=?ANDVOLTAGE=?";

m_pSet->p1="电动机";

m_pSet->p2=60.0;

m_pSet->Requery();
 

参变量的值按绑定的顺序替换 查询字串中的“?”适配符。

如果查询的结果是多条记录的 话,可以用CRecordSet类的函数Move(),MoveNext(),MovePrev(),MoveFirst() 和MoveLast()来移动光标。

#4


简单一点说就是在你的open()里的strSQL,不要带where条件。就可以用requery了。

#5


TO: laiyiling(陌生人)
1). 我摘了循环里的一段代码而已,
int =1;if(...)
{ CString searchid;
  searchid.Format("ID=%d",i);
  strSQL.Format("select * from person where %s",searchid);
这样SQL语句就是"select * from person where ID=1".
是为了每次循环针对i变换查询条件。
2).m_recordset->Open(CRecordset::dynaset,str_SQL,CRecordset::dynaset);这样改了后还是不行,是不是和我用CLASS WIZARD创建CRecordSet的关联有关?我看CLASS WIZARD里member variable数据库数据下面有这么一句“binding varchar column to CString field”??

TO: zhangqu_980371(能坚持一辈子的东西太少)
我就是看这个学的,你能按我想要的目的给个正确的用法么??
就是开始OPEN的时候用自定义的SQL语句,后面通过改过滤参数再REQUERY?我只有用默认的语句才不出错。

再说明一下,我贴的代码是可以运行的,就是按我说的用注释掉的B句换去A才出现的问题。
//这样可以-》
   m_recordset.m_strFilter=searchid;//利用成员变量来操作的(A)两句
   m_recordset.Open(AFX_DB_USE_DEFAULT_TYPE,NULL);//用默认语句
   m_recordset.m_strFilter="NAME='vfcgf'";
    //不关闭m_recordset做连续的第2次查询,
   m_recordset.Requery();

//这样就不行-》
   m_recordset.Open(AFX_DB_USE_DEFAULT_TYPE,strSQL);//××××利用自定义sql语句来操作的语句(B)
   m_recordset.m_strFilter="NAME='vfcgf'";
   //不关闭m_recordset做连续的第2次查询,
   m_recordset.Requery();

#6


TO: zhangqu_980371(能坚持一辈子的东西太少) 
那岂不是说开始的时候不能设定条件查询?

#7


哦,明白了,只能按它的规矩楼。

谢谢大家。
现在就剩下dynaset的问题了。我又做了个小的DEMO,用CLASS WIZARD产生记录集的类。
CPersonSet::CPersonSet(CDatabase* pdb)
: CRecordset(pdb)
{ //{{AFX_FIELD_INIT(CPersonSet)
m_ID = 0;
m_NAME = _T("");
m_nFields = 2;
//}}AFX_FIELD_INIT
m_nDefaultType = snapshot;//这里不一样
}
CMYSet::CMYSet(CDatabase* pdb)
: CRecordset(pdb)
{
//{{AFX_FIELD_INIT(CMYSet)
m_PASSWORD = _T("");
m_nFields = 1;
//}}AFX_FIELD_INIT
m_nDefaultType = dynaset;//这里不一样
}
Open的时候用
CMYSet *m_set=new CMYSet(&m_database);
m_set->Open(CRecordset::dynaset,sql,CRecordset::dynaset);

CPersonSet *m_p=new CPersonSet(&m_database);
m_p->Open(CRecordset::dynaset,sql2,CRecordset::dynaset);
都没有出提示:“ODBC驱动程序不支持动态记录集”。
郁闷啊,真不知道我那个这里出问题程序为什么
从Open(AFX_DB_USE_DEFAULT_TYPE,sql);
换成Open(CRecordset::dynaset,sql,CRecordset::dynaset);就出问题???
既然继承类的构造函数里有参数设置m_nDefaultType = dynaset;
那么用AFX_DB_USE_DEFAULT_TYPE和用CRecordset::dynaset不是应该一样么?

#8


我跟踪了下,出错的位置在//————————标识处
CPassSet* m_paset = new CPassSet(&m_database);
CString sql;
sql.Format("select * from password where PASSWORD='%s'",m_edit_pass);
m_paset->Open(CRecordset::dynaset,sql,CRecordset::dynaset);
if(m_paset->GetRecordCount()==0)
{
    if(counts<3)
    {
        AfxMessageBox("口令错误!");
        counts++;
        m_edit_pass.Empty();
        m_ctrpass.SetFocus();
        UpdateData(FALSE);
    }
    else
    {
        MessageBox("你无权使用此系统!","警告",MB_OK|MB_ICONHAND);
        m_database.Close();
        CDialog::OnOK();
    }
}
else
{
          //密码正确的话关闭当前数据库连接并弹出主对话框-----》
    m_database.Close();
    CMainDlg maindlg;
    maindlg.m_database.Open(_T("addresslist"));//是不是这里导致后面出问题???
    KillTimer(0);
    CDialog::OnOK();
    maindlg.DoModal();//—————运行到这里时出错:“ODBC驱动程序不支持动态记录”
}
我也不是太清楚,maindlg.m_database.Open(_T("addresslist"));//是不是这里导致后面出问题???


#9


Open(_T("addresslist"));//是不是这里导致后面出问题???

当然出问题啊。这个open里面是数据源连接字符串,你的是”addresslist“
又怎么能打开数据库啊。

呵呵,手头刚好有个跟你的要求一模一样的例子,要的话发给你好。然后你分析一下好点。
QQ:82591254

#10


还是留下email吧。

#11



我的我之前用Open(AFX_DB_USE_DEFAULT_TYPE,sql);的方式的时候
m_nDefaultType = snapshot;
代码里有这样Open(_T("addresslist"));的方式没问题。addresslist是我的数据源名称。

现在我理解的是这样打开和动态打开产生矛盾把,对把?

谢谢!!大家,揭贴了。
我的信箱wxlran@tom.com

#12


呵呵,已经发过去了!

推荐阅读
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • ALTERTABLE通过更改、添加、除去列和约束,或者通过启用或禁用约束和触发器来更改表的定义。语法ALTERTABLEtable{[ALTERCOLUMNcolu ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • Ihavethefollowingonhtml我在html上有以下内容<html><head><scriptsrc..3003_Tes ... [详细]
author-avatar
香樟树1016
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有