请教多条件查询优化问题

huziwu 2008-04-16 04:03:14
前提:
1.使用ADO编程访问access数据库
2.实现语言转换,例如我现在有一个数组CString Lang1[100],还有一张中英文对照表language,结构为:sLanguage,chinese,english等语言字段.
3.调用函数ChangeLanguage(CString *sLang,CString *dLang,int size,CString Language);//实现语言转换
CString *sLang//原始语言
CString *dLang//目标语言
int size;//语言数,也即字符串数(数组长度)
CString Language;//语言类型
我的相法是这样的:

BOOL ChangeLanguage(CString *sLang,CString *dLang,int size,CString Language)
{
_ConnectionPtr m_pConnection;
AfxOleInit();
m_pConnection.CreateInstance(__uuidof(Connection));
try
{
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=language.mdb","","",adModeUnknown);
_RecordsetPtr m_pRecordset;
m_pRecordset.CreateInstance(__uuidof(Recordset));
CString csSql;
_variant_t var;

方法一:
for(int i=0;i<size;i++)
{
csSql.Format("Select * From Language where sLanguage='%s'",sLang[i]);
m_pRecordset->Open(_bstr_t(cmd),theApp.m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
var=m_pRecordset->GetCollect(_bstr_t(Language));
if(var.vt!=VT_NULL)
dLang[i]=(LPCSTR)_bstr_t(var);
else
dLang[i].Empty();
m_pRecordset->Cloes();
}

}
catch(_com_error e)
{
AfxMessageBox("错误信息!");
return FALSE;
}
return TRUE;
}

方法二:
csSql.Format("Select * From Language where sLanguage='%s'",sLang[0]);
for(int i=0;i<size;i++)
{
csSql.Format(" or sLanguage='%s'",sLang[i]);
}

m_pRecordset->Open(_bstr_t(cmd),theApp.m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
while(!m_pRecordset->adoEOF)
{
var=m_pRecordset->GetCollect(_bstr_t(Language));
if(var.vt!=VT_NULL)
dLang[i]=(LPCSTR)_bstr_t(var);
else
dLang[i].Empty();
m_pRecordset->MoveNext();
}
m_pRecordset->Cloes();


方法一:实现起来速度有点慢,原数组很多的情况下;
方法二:同样在数组很多的情况下,条件太长会不会有问题,还有这样获得的结果排序也存在问题,会跟原语言对不上,即第一个源字符串,与第一个目标字符串不对应了。也考虑过采用in关键字但排序问题还是存在
不知可不可以采用m_pConnection->execl()方法来实现呢,这样就不用重复打开表了,可以的话请给个例子,谢谢
请大家多给些意见,帮忙想下办法,先在此谢过大家了!
...全文
330 39 打赏 收藏 转发到动态 举报
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
shakaqrj 2008-04-22
  • 打赏
  • 举报
回复
表中的内容很多么?
不多的话
读入到一个stl容器中,比如map
huziwu 2008-04-22
  • 打赏
  • 举报
回复
我实际用的表里是有建索引的,因为我前面还有一个ID字段,此字段以升序排序的
我以前的做法也是通过ini文件进行转换的,速度快很多,大概也就1-3秒就转换完成,现在要求要用数据库来存款这些信息,晕死了.
huziwu 2008-04-22
  • 打赏
  • 举报
回复
第3,4个参数用adOpenForwardOnly,adLockReadOnly速度会快点,单次执行时间为109-125ms
shakaqrj 2008-04-22
  • 打赏
  • 举报
回复
一般动态切换不是通过数据库,因为没什么管理的,是通过ini文件
shakaqrj 2008-04-22
  • 打赏
  • 举报
回复
索引不是针对程序中的变量
是表中的字段
huziwu 2008-04-22
  • 打赏
  • 举报
回复
说明一下,我一次只找一个,而且sLang[]并不是有序的,它的值可能是这样sLang[0]=100,sLang[1]=5,sLang[2]=200...
这样索引还有用吗?
还有就是我一次软换最多也不会超过200个字符串,但会多次转换。
例如:我按下语言转换时要对多个窗口进行语言转换的
for(int i=0;i<100;i++)//这样要16秒才能执行完成,这样等待的时间感觉太长了,将50换成200就更慢了
ChangeLanguage(sLang,dLang,50,"Chinese");
shakaqrj 2008-04-22
  • 打赏
  • 举报
回复
可能50个不多
存储过程第一次执行速度会比普通的sql慢,后面才体现出优势
你建索引
另外第3,4个参数用这个adOpenForwardOnly,adLockReadOnly
huziwu 2008-04-22
  • 打赏
  • 举报
回复
试了shakaqrj的方法,可以调用查询。但是速度反而更慢了,比我前面用的方法一还慢。
我用50个字符串进行查询,调用查询运行的时间最快为156毫秒,而采用我原来的方法(通过条件打开表)最快时为141ms。

调用查询:
for(int i=0;i <size;i++)
{
csSql.Format("a '%s'",sLang[i]);
m_pRecordset->Open(_bstr_t(cmd),theApp.m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdStoredProc);
var=m_pRecordset->GetCollect(_bstr_t(Language));
if(var.vt!=VT_NULL)
dLang[i]=(LPCSTR)_bstr_t(var);
else
dLang[i].Empty();
m_pRecordset->Cloes();
}

通过条件打开表:
for(int i=0;i <size;i++)
{
csSql.Format("Select * From Language where Src_Name='%s'",sLang[i]);
m_pRecordset->Open(_bstr_t(cmd),theApp.m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
var=m_pRecordset->GetCollect(_bstr_t(Language));
if(var.vt!=VT_NULL)
dLang[i]=(LPCSTR)_bstr_t(var);
else
dLang[i].Empty();
m_pRecordset->Cloes();
}
shakaqrj 2008-04-22
  • 打赏
  • 举报
回复
查询名是a
SELECT *
FROM [Language]
WHERE Src_Name=[slang];
shakaqrj 2008-04-22
  • 打赏
  • 举报
回复
m_pRecordset->Open("a '1'",_variant_t(m_pConn,true),adOpenStatic,adLockOptimistic,adCmdStoredProc);
这样吧
shakaqrj 2008-04-22
  • 打赏
  • 举报
回复
备注...
我得先试试看了
为什么不用文本类型?
huziwu 2008-04-22
  • 打赏
  • 举报
回复
我是使用关键字in将符合条件的记录先一次性找出来,再进行排序赋值,原来的做是法一条一条去获得,就不用排序赋值。
我把代码贴出来你就知道了。
CString cmd;
cmd.Format("Select * from [language] where Src_Name in ('%s'",sLang[0]);
for(int i=1;i<Size;i++)
{
cmd.Format(cmd+",'%s'",sLang[i]);
}
cmd.Format(cmd+")");//加上后面的括号
m_pRecordset->Open(_bstr_t(cmd),theApp.m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);

CString tmpSrc;
while(!m_pRecordset->adoEOF)
{
tmpSrc=(LPCSTR)_bstr_t(m_pRecordset->GetCollect("Src_Name"));
for(i=0;i<Size;i++)
{
if(tmpSrc==sLang[i])
{
dLang[i]==(LPCSTR)_bstr_t(m_pRecordset->GetCollect(_bstr_t(LangType)));
break;//若是源字符串中有相同的,则不能break;要不然后面的找不到
}
}
m_pRecordset->MoveNext();
}
m_pRecordset->Close();
采用上面的代码,速度会快很多,而且我试过,当Size=10000时,也不会报错,只是会慢一点,但比原来的方法就快很多,说明in()里面的内容可能达到10000或更多,而where条件最多好像只能255个
shakaqrj 2008-04-22
  • 打赏
  • 举报
回复
为虾米要用in?
为虾米要用范围?
shakaqrj 2008-04-22
  • 打赏
  • 举报
回复
恩?
你到底是要做什么?
我都有点看不懂了
huziwu 2008-04-22
  • 打赏
  • 举报
回复
to:shakaqrj
stl容器怎么用呢?我还是头一次听过这个:(

不算多,表中内容大概也就1万条记录左右
我发现用in关键字列出所有条件,再对找出的结果进行排序,那样会快很多,测试时间只要16ms,比原来的方法快了接近10倍
而且in关键字里包括的内容好像也没有限制,我用1万个条件做测试也通过了。
例如:Select * from [language] where Src_Name in ('1','2',……,'10000');

buyong 2008-04-21
  • 打赏
  • 举报
回复
直接recordset打开不就行了,干嘛先connection?
huziwu 2008-04-21
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 huziwu 的回复:]
怎么又变成open了呢,不是execute吗?
我都快搞疯了,问题我前面都说了,是不是没说清楚啊?能不能直接帮我把实现代码写出来呢?数据库我刚接触很多东西都没搞明白啊!!!!

我从新说一下我的问题:
数据库名:language.mdb(access)
表:language
表结构
Src_Name(备注) chinese(备注) english(备注)
1 一 one
2 二 two

[/Quote]
huziwu 2008-04-21
  • 打赏
  • 举报
回复
Src_Name 就是sLanguage,后来我改名了,是备注类型
huziwu 2008-04-21
  • 打赏
  • 举报
回复
晕,我怎么看不到后面的回复了,只能看到18楼,回复有20了,后面两个看不到!!!!
shakaqrj 2008-04-21
  • 打赏
  • 举报
回复
没搞明白Src_Name=sLang
Src_Name字段名?没看到定义阿
还有,字段都是什么类型的?
加载更多回复(19)

4,011

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 数据库
社区管理员
  • 数据库
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧