【原创】7. MYSQL++中的查询结果获取(各种Result类型)
2014-03-30 09:56
337 查看
在本节中,我将首先介绍MYSQL++中的查询的几个简单例子用法,然后看一下mysqlpp::Query中的几个与查询相关的方法原型(重点关注返回值),最后对几个关键类型进行解释。
1.MYSQL++的查询实例
下面的两个例子分别是STORE(所有数据一次性从服务器拉到本地缓存)和USE(将数据一条一条从服务器拉到本地)的使用方式,其中STORE内部实质就是mysql_store(),而USE实质就是调用了mysql_use()。
说明,下面的例子虽然使用的都是最为基本的查询过程(即没有使用templatesql或者SSQLS),但是这个并不影响我们的讨论,因为遍历结果集的过程是一致的。
STORE
USE
从上面的两个例子中我们大致可以看出来,整个结果集的查询过程就是针对相匹配的Result类型,找到ROW,然后逐行或者跳跃着查找。
2.Result相关类型的使用场合
首先让我们回顾mysqlpp::Query中提到的几个方法,以及他们的返回值。以下部分内容直接摘自关于mysqlpp::Query的介绍的内容。
为了讲述方便,我们先来看一下在result.h(DeclaresclassesforholdinginformationaboutSQLquery)中所定义的各种类型的关系。这几个类型后面会仔细说明。
1)
这里返回的是bool,表示的是“语句是否执行成功”,我认为适合于那种update,delete,insert,且都不关心有多少rows被touch的情况。
2)
这里的SimpleResult正如其名,其中只有如下信息
(ulonglonginsert_id()const)
(ulonglongrows()const)
anyadditionalinformationaboutthequeryreturnedbytheserver(constchar*info()const)
3)
由于use的语义类似于使用游标,也就是支持一行一行地拉出内容,所以UseQueryResult也就自然而然地支持一些关于fetchrow的功能。
4)
StoreQueryResult它本身就是从vector<Row>继承而来,所以它就是vector。所以用户程序可以直接使用下标的形式来获取所有的ROW。这也就是说在这个store之后,所有的ROW的内容都在了这个vecor<Row>里面了。
3.Result相关类型解析
与Result相关的类型主要集中在result.h和result.cpp。
1)SimpleResult
这个类型非常简单,是一个比较单纯的类型,并没有父类。主要的成员变量有3个,分别是
成员方法也比较单纯,就是对上述几个字段的GET,构造函数就是对上述几个字段的SET。
以SimpleResultmysqlpp::Query::execute();为例,让我们来看一下MYSQL++是如何设置这个SimpleResult。
再来看一下Query::insert_id(),Query::affected_rows(),Query::info(),这几个方法都直接delegateDBDriver的相关函数,直接返回了结果而已。
2)ResultBase
这个类型是StoreQueryResult和UseQueryResult的父类型,该类型其实没有特别的含义,只是作为一个commonmethods的container而已。但是该类型提供的几乎所有的publicmethods都是和fields有关的,包括了
根据index查找field;
根据name查找field;
根据index查找到field的名字和属性类型;
获取当前所在的field(ResultBase内部会有一个mutable的index名为current_field_用于指明当前fetch_field的是哪一个field,在fetch_field中该index会自增)
该类型的核心成员有如下几个
Fields(std::vector<Field>)类型的fields_
FieldNames(继承自std::vector<std::string>)类型的names_
FieldTypes(继承自std::vector<mysql_type_info>)类型的types_
其中FieldNames和FieldTypes都是被RefCountedPointer包裹着,估计这样做能够节省空间。关于Field类型在后续进行介绍。至于刚才说的几个找field的操作,看着这几个核心成员的类型还是比较好理解的。不就是在vector中不找。
需要额外关注的是以下这个最主要的构造函数
以下几点需要注意,
names_和types_在new出来之后是不需要显式delete的,因为他们都在智能指针RefCountedPointer包裹着。
成员初始化列表中的fields_(Fields::size_type(…))这一句其实调用的是
1.MYSQL++的查询实例
下面的两个例子分别是STORE(所有数据一次性从服务器拉到本地缓存)和USE(将数据一条一条从服务器拉到本地)的使用方式,其中STORE内部实质就是mysql_store(),而USE实质就是调用了mysql_use()。
说明,下面的例子虽然使用的都是最为基本的查询过程(即没有使用templatesql或者SSQLS),但是这个并不影响我们的讨论,因为遍历结果集的过程是一致的。
STORE
mysqlpp::Queryquery=conn.query("selectitemfromstock"); mysqlpp::StoreQueryResultres=query.store(); mysqlpp::StoreQueryResult::const_iteratorit; for(it=res.begin();it!=res.end();++it) { mysqlpp::Rowrow=*it; //第一列row[0] //第二列row[1] }
USE
mysqlpp::Queryquery=conn.query("select*fromstock"); mysqlpp::UseQueryResultres=query.use(); while(mysqlpp::Rowrow=res.fetch_row()) { row["item"]; row["num"]; } //Checkforerror: //can'tdistinguish"endofresults"and //errorcasesinreturnfromfetch_row()otherwise if(conn.errnum()) { cout<<"Errorinfetch_row"; }
从上面的两个例子中我们大致可以看出来,整个结果集的查询过程就是针对相匹配的Result类型,找到ROW,然后逐行或者跳跃着查找。
2.Result相关类型的使用场合
首先让我们回顾mysqlpp::Query中提到的几个方法,以及他们的返回值。以下部分内容直接摘自关于mysqlpp::Query的介绍的内容。
为了讲述方便,我们先来看一下在result.h(DeclaresclassesforholdinginformationaboutSQLquery)中所定义的各种类型的关系。这几个类型后面会仔细说明。
1)
boolmysqlpp::Query::exec(conststd::string&str);
这里返回的是bool,表示的是“语句是否执行成功”,我认为适合于那种update,delete,insert,且都不关心有多少rows被touch的情况。
2)
SimpleResultmysqlpp::Query::execute();
这里的SimpleResult正如其名,其中只有如下信息
thelastvalueusedforanAUTO_INCREMENTfield
(ulonglonginsert_id()const)
thenumberofrowsaffectedbythequery
(ulonglongrows()const)
anyadditionalinformationaboutthequeryreturnedbytheserver(constchar*info()const)
3)
UseQueryResultmysqlpp::Query::use();
由于use的语义类似于使用游标,也就是支持一行一行地拉出内容,所以UseQueryResult也就自然而然地支持一些关于fetchrow的功能。
4)
StoreQueryResultmysqlpp::Query::store();
StoreQueryResult它本身就是从vector<Row>继承而来,所以它就是vector。所以用户程序可以直接使用下标的形式来获取所有的ROW。这也就是说在这个store之后,所有的ROW的内容都在了这个vecor<Row>里面了。
3.Result相关类型解析
与Result相关的类型主要集中在result.h和result.cpp。
1)SimpleResult
这个类型非常简单,是一个比较单纯的类型,并没有父类。主要的成员变量有3个,分别是
//lastvalueusedforanAUTO_INCREMENTfield
ulonglonginsert_id_;
//thenumberofrowsaffectedbythequery
ulonglongrows_;
//anyadditionalinformationaboutthequeryreturnedbytheserver
std::stringinfo_;
成员方法也比较单纯,就是对上述几个字段的GET,构造函数就是对上述几个字段的SET。
以SimpleResultmysqlpp::Query::execute();为例,让我们来看一下MYSQL++是如何设置这个SimpleResult。
再来看一下Query::insert_id(),Query::affected_rows(),Query::info(),这几个方法都直接delegateDBDriver的相关函数,直接返回了结果而已。
2)ResultBase
这个类型是StoreQueryResult和UseQueryResult的父类型,该类型其实没有特别的含义,只是作为一个commonmethods的container而已。但是该类型提供的几乎所有的publicmethods都是和fields有关的,包括了
根据index查找field;
根据name查找field;
根据index查找到field的名字和属性类型;
获取当前所在的field(ResultBase内部会有一个mutable的index名为current_field_用于指明当前fetch_field的是哪一个field,在fetch_field中该index会自增)
该类型的核心成员有如下几个
Fields(std::vector<Field>)类型的fields_
FieldNames(继承自std::vector<std::string>)类型的names_
FieldTypes(继承自std::vector<mysql_type_info>)类型的types_
其中FieldNames和FieldTypes都是被RefCountedPointer包裹着,估计这样做能够节省空间。关于Field类型在后续进行介绍。至于刚才说的几个找field的操作,看着这几个核心成员的类型还是比较好理解的。不就是在vector中不找。
需要额外关注的是以下这个最主要的构造函数
以下几点需要注意,
names_和types_在new出来之后是不需要显式delete的,因为他们都在智能指针RefCountedPointer包裹着。
成员初始化列表中的fields_(Fields::size_type(…))这一句其实调用的是
explicitstd::vector::vector(size_typen,constvalue_type&val=value_type(),constallocator_type&alloc=allocator_type());
从以上构造函数可以看到,其实关于Field的信息还是从DBDriver中拿到的,然后关于FieldNames和FieldTypes的信息,则是通过这两个类型自身的构造函数给实现的(其实就是收到ResultBase*,然后遍历其中的成员变量fields_再各求所需罢了。
为什么要有重新将指示field_当前index的指针重置的过程(dbd->field_seek(res,0))?这是因为方便这个DBDriver再次循环访问这些fields。
3)StoreQueryResult
该类型是同时集成了ResultBase和vecor<Row>类型(请注意了,这个Result居然是一个vecor<Row>!)文档中说,该类型holdresultsfromaSQLquerythatreturnsrows:aspecializationofstd::vectorholdingRowobjectsinmemorysoyougetrandom-accesssemantics.
说白了,该类型在继承了ResultBase之后,只有以下这个构造函数是比较要紧的了。
有以下几点需要说明
StoreQueryResult继承自std::vector<Row>
在成员初始化列表中,首先调用ResultBase的构造函数
list_type是std::vector<Row>的typedef,所以在list_type(…)这一行,直接根据DBDriver返回的结果的rows的数量就布置好了vector的长度。
MYSQL_ROW是MYSQL自带的结构类型(定义域mysql.h中,typedefchar**MYSQL_ROW;)
dbd->fetch_row(MYSQL_RES*)应该只是包装了mysql_fetch_row(MYSQL_RES*)这个MySqlCAPI,而dbd->fetch_lengths(MYSQL_RES*)其实包装的是mysql_fetch_lengths(MYSQL_RES*)这个MYSQLCAPI,他获取的是整个row的对应的所有field的长度。
这一次Query的结果在全部拷贝完之后就释放了(dbd->free_result(res);)
如此一来,所有我们需要的信息都通过构造一个mysqlpp::Row对象来实现了。关于mysqlpp::Row的具体说明请看下文。
4)UseQueryResult
该类型拓展于ResultBase类型。根据MYSQL++userdocument的说法,UseQueryResule适用于Fortheselargeresultsets,a“use”querytellsthedatabaseservertosendtheresultsbackonerowatatime,tobeprocessedlinearly.
该类型的方法比StoreQueryResult丰富多了,主要体现在:
可以顺序读取行(mysqlpp::Rowfetch_row()const;或者MYSQL_ROWfetch_raw_row()const;)
可以获取当前行的各个field的信息(constField&fetch_field()const;constField&fetch_field(Fields::size_typei)const)
可以获取当前行的所有fields的长度(constunsignedlong*fetch_lengths()const;)
值得注意的是,UseQueryResult有一个成员变量
mutableRefCountedPointer<MYSQL_RES>result_;
需要强调的有两点
MYSQL_RES是MYSQLCAPI中的用于做为资源的结构体,获取一行的函数mysql_fetch_one_row的参数就是MYSQL_RES*
RefCountedPointer是一个智能指针,但是就在定义这些result类型的result.h中,作者将其针对MYSQL_RES进行了具化,即
很显然,这个是为了在refcount为0时自动调用析构器而准备的,该Destroyer使用mysql_free_result来销毁这里的result_,从而代替默认的delete操作。
接下来,我们来具体看几个函数的实现。
构造函数
获取fields的信息
请注意,这个result_是一个RefCountedPointer<MYSQL_RES>,所以调用的raw方法将会返回MYSQL_RES*
获取一行数据
核心的做法就是利用MYSQL_ROWDBDriver::fetch_row(MYSQL_RES*res)const。其实质也就是调用了mysql_fetch_one_row()这个CAPI。然后直接生成一个mysqlpp::Row对象,返回。
相关文章推荐
- [mysql]当mysql查询语句查询的结果为空时,返回query结果是什么类型的呢?
- Python中让MySQL查询结果返回字典类型的方法
- Oracle数据库中字段定义为Char类型,Hibernate用该字段进行动态绑定参数查询,获取不到结果的问题
- Java获取数据库各种查询结果
- JAVA连接MYSQL通过查询返回的结果集获取表结构字段类型
- MYSQL使用float类型精确查询结果为空
- MySQL的JDBC判断查询结果是否为空以及获取查询结果行数的方法
- Python中让MySQL查询结果返回字典类型的方法
- Python中让MySQL查询结果返回字典类型的方法
- MySQL 获取某一个分类ID的所有父或子分类查询结果
- Python中让MySQL查询结果返回字典类型的方法
- PHP使用mysql_fetch_object从查询结果中获取对象集的方法
- 使用SpringData JPAQL获取查询结果query.getResultList()读取后EntityManager会自动关闭
- 直接从命令行获取MySQL查询语句结果
- MYSQL使用float类型精确查询结果为空
- MyBatis查询结果resultType返回值类型详细介绍
- mybatis mysql 关于调用存储过程获取查询结果
- 应用mysql_num_rows()函数获取查询结果集中的记录数
- mysql查询各种类型的前N条记录
- Struts2 result type(结果类型)