前面两讲说到了,安装MySql数据库,安装ODBC驱动以及使用CDatabase操作数据库的基本操作比如Add del edit,链接如下:
visual c++ 2008进行MySQL编程(ODBC) -- (一) 套装安装
visual c++ 2008进行MySQL编程(ODBC) --(二) CDatabase操作数据库
今天引入一个新的类,CRecordset,其实前面的编程操作对于CRecordset类而言,相对而言就非常的弱小了呵呵,后续一一说到吧。今天的工作就是使用这个类遍历一下我们数据库里面的条目。
继续在上一个文章的工程上做这一切。
一、在对话框里面托一个listtree控件,修改属性为报表模式:
上图的黄色的框框的属性要修改report,报表格式。
二、给这个新加的list control添加成员变量,m_list_ctrl:
三、在Cmy_dbDlg类的初始化函数OnInitDialog()里面添加添加的list control的初始化代码:
1. m_list_ctrl.InsertColumn( 0, _T("Cust Id"), LVCFMT_CENTER, 70 );//插入列
2. m_list_ctrl.InsertColumn( 1, _T("Cust Name"), LVCFMT_CENTER, 85 );
四、添加一个按钮,用作查询,同时给这个按钮添加Cmy_dbDlg的单击响应函数:
查询的按钮就是上图的GetRecord。
消息响应函数为:
1. void Cmy_dbDlg::OnBnClickedGetAllItem()
2. {
3. // TODO: Add your control notification handler code here
4. }
四、现在来实现这个消息函数,我们使用类CRecordset,具体的要使用的函数,我们看看MSDN的文档:
1. Opens the recordset by retrieving the table or performing the query that the recordset represents.
2. virtual BOOL Open(
3. UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE,
4. LPCTSTR lpszSQL = NULL,
5. DWORD dwOptions = none
6. );
7.
8. Returns nonzero if the recordset has been positioned before the first record. There is no current record.
9. BOOL IsBOF( ) const;
10.
11. Returns nonzero if the recordset has been positioned after the last record. There is no current record.
12. BOOL IsEOF( ) const;
13.
14. Makes the first record in the next rowset the current record.
15. void MoveNext( );
16.
Open函数打开指定的数据库,之后才可以遍历,如果数据库为空,则IsBOF返回true,如果需要遍历每一条,则使用MoveNext( )。
使用起来就是这么简单。
五、OnBnClickedGetAllItem()的实现修改如下:
1. void Cmy_dbDlg::OnBnClickedGetAllItem()
2. {
3. // TODO: Add your control notification handler code here
4. CRecordset my_record(&m_db_opr);
5.
6. try
7. {
8. int count = 0;
9. CString str;
10.
11. "select * from customer"));
12.
13. if(my_record.IsBOF())
14. {
15. return;
16. }
17.
18. while(!my_record.IsEOF())
19. {
20. short)0, str);
21. m_list_ctrl.InsertItem(count, str);
22.
23. my_record.GetFieldValue(1, str);
24. m_list_ctrl.SetItemText(count, 1, str);
25.
26. my_record.MoveNext();
27. count++;
28. }
29. }
30. catch(CDBException* pe)
31. {
32. // The error code is in pe->m_nRetCode
33. pe->ReportError();
34. pe->Delete();
35. }
36. }
现在解释一下上面的代码吧,Open函数还是请大家参考一下MSDN呵呵,第一个参数可以为:
- 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 A read-only recordset with only forward scrolling.
For CRecordset, the default value is CRecordset::snapshot. The default-value mechanism allows the Visual C++ wizards to interact with both ODBCCRecordset and DAOCDaoRecordset, which have different defaults.
具体我就不翻译了,mysql的ODBC貌似只支持snapshot,就是快照,静态的获取当前的数据库里面的条目数。
Open的第二个参数,是一个字符串,就是用于查询数据库的的sql语句。
编译代码,运行,我们执行一下,单击GetRecord按钮就能查询到当前的所有条目,如图:
挺完美对吧。
还没有结束,还要继续说说如何设定查询范围,设定排序方式等等。
六、我们设定过滤规则,比如我想要查询100<= x <= 200范围内的cust id的条目,如何进行?
解决这个问题需要求助于
m_strFilter
1. my_record.m_strFilter = _T("cust_id <= 200 and cust_id >= 100");
2.
3. my_record.Open(CRecordset::snapshot, _T("select * from customer"));
那么修改后面的OnBnClickedGetAllItem函数如下:
1. void Cmy_dbDlg::OnBnClickedGetAllItem()
2. {
3. // TODO: Add your control notification handler code here
4. CRecordset my_record(&m_db_opr);
5.
6. try
7. {
8. int count = 0;
9. CString str;
10.
11. "cust_id <= 200 and cust_id >= 100");
12.
13. "select * from customer"));
14.
15. if(my_record.IsBOF())
16. {
17. return;
18. }
19.
20. while(!my_record.IsEOF())
21. {
22. short)0, str);
23. m_list_ctrl.InsertItem(count, str);
24.
25. my_record.GetFieldValue(1, str);
26. m_list_ctrl.SetItemText(count, 1, str);
27.
28. my_record.MoveNext();
29. count++;
30. }
31. }
32. catch(CDBException* pe)
33. {
34. // The error code is in pe->m_nRetCode
35. pe->ReportError();
36. pe->Delete();
37. }
38. }
我们可以看到,查询结果如下图:
但是我们知道,设定查询范围怎么弄?需要where 子句,比如 :
select * from customer where cust_id <= 200 and cust_id >= 100;
但是使用了m_strFilter这个作为过滤规则的设定,就不能使用带上where了。
七、我们可以设定排序规则,比如按照cust id排序,而且是逆序,这个操作就要借助于
m_strSort
了,也只要设定排序对象就是了:
1. my_record.m_strFilter = _T("cust_id <= 200 and cust_id >= 100");
2.
3. my_record.m_strSort = _T("cust_id desc");
4. my_record.Open(CRecordset::snapshot, _T("select * from customer"));
- 和上面过滤的规则一样,sql语句是需要Order by子句的,如果使用了m_strSort之后,那么就不能有“order by”了,而这个语句:
- my_record.m_strSort = _T("cust_id desc");
- 就相当于, “order by cust_id desc” 子句了。
- 修改后的消息响应函数就是这个样子的了:
1. void Cmy_dbDlg::OnBnClickedGetAllItem()
2. {
3. // TODO: Add your control notification handler code here
4. CRecordset my_record(&m_db_opr);
5.
6. try
7. {
8. int count = 0;
9. CString str;
10.
11. "cust_id <= 200 and cust_id >= 100");
12. "cust_id desc");
13.
14. "select * from customer"));
15.
16. if(my_record.IsBOF())
17. {
18. return;
19. }
20.
21. while(!my_record.IsEOF())
22. {
23. short)0, str);
24. m_list_ctrl.InsertItem(count, str);
25.
26. my_record.GetFieldValue(1, str);
27. m_list_ctrl.SetItemText(count, 1, str);
28.
29. my_record.MoveNext();
30. count++;
31. }
32. }
33. catch(CDBException* pe)
34. {
35. // The error code is in pe->m_nRetCode
36. pe->ReportError();
37. pe->Delete();
38. }
39. }
40. 执行一下程序,自然就逆序打印了: