终于他妈可以上图了,唉,继续吧。
本来是想做上下两次说完的,东西太多了,一次写完,我累,看起来也累。
接上一篇文章讲吧,前面说到了具体的Mysql的ODBC驱动配置,链接如下:
visual c++ 2008进行MySQL编程(ODBC) -- (一) 套装安装
visual c++ 2008进行MySQL编程(ODBC) --二 操作数据库
visual c++ 2008进行MySQL编程(ODBC) --三 查询数据库
visual c++ 2008进行MySQL编程(ODBC)-- (四) 终极实现 之 派生CRecordset 上
visual c++ 2008进行MySQL编程(ODBC)-- (四) 终极实现 之 派生CRecordset 中
visual c++ 2008进行MySQL编程(ODBC)-- (四) 终极实现 之 派生CRecordset 下
数据库可以有两种方式编程,第一种直接使用class CDatabase,然后执行一些没有返回内容的操作,比如增删和修改,查询就做不了啦。
这次就说这个类功能。
首先vc创建一个MFC基于对话框的工程,我们要做上面说的一些操作数据库的编码操作了:
创建一个纯种的对话框,呵呵:
生成的dialog,我们添加我们要的东西:
现在查看一下类视图,可以看到如下:
我要做的操作,都是在类Cmy_dbDlg这个里面操作了。
第一件事情就是在这个类定义里面添加一个类成员,私有成员:CDatabase m_db_opr;
private: CDatabase m_db_opr;
在这个类所在的头文件里面添加文件:
#include "afxdb.h"
否在添加的db类,找不到定义的。
找到类Cmy_dbDlg里面定义的函数:
virtual BOOL OnInitDialog();
我们要在里面添加数据库初始化代码的(函数靠近最后面吧):
m_db_opr.Open(NULL, false, false, _T("ODBC;server=127.0.0.1;DSN=chh1;UID=zhoutianzuo;PWD=000000") ); if(!m_db_opr.IsOpen()) { AfxMessageBox(_T("DB open failed!")); return false; }
上面的代码解释一下:数据库变量用默认构造函数就行了,所以不用在对话框的类构造函数里面做什么了,然后就是打开数据库,调用db成员的Open函数,示例里面最后一个传入参数,第一个表示ODBC驱动方式,第二个参数,表示本机server,DSN就是前面一讲里面说的数据库名称,后面就是用户名和密码了。
接下来要判断一下数据库是否打开了,不成功,弹出错误窗口,直接报错了。
回到开始拉控件的对话框,我们给编辑控件添加类的私有的成员变量m_cust_id,m_cust_name:
上图是添加cust id,添加cust name一致。
接下来,给addnew这个按钮添加单击事件:
上图中,我们添加消息响应函数为OnBnClickedAddNew,点击Add and Edit按钮。代码如下:
void Cmy_dbDlg::OnBnClickedAddNew() { // TODO: Add your control notification handler code here }
如上,接着添加Edit和Delete的事件。代码如下:
void Cmy_dbDlg::OnBnClickedEdit() { // TODO: Add your control notification handler code here } void Cmy_dbDlg::OnBnClickedDelete() { // TODO: Add your control notification handler code here }
最开始已经说了,我们这里只介绍CDatabase类,所以,所有操作都是这个类的,而实现增删和修改的依托就是成员函数:
Call this member function when you need to execute a SQL command directly. void ExecuteSQL( LPCTSTR lpszSQL ); Parameters lpszSQL Pointer to a null-terminated string containing a valid SQL command to execute. You can pass a CString.
上面的介绍来自MSDN文档介绍。
还有一个函数:
Call this member function to determine whether the CDatabase object allows updates. BOOL CanUpdate( ) const; Return Value Nonzero if the CDatabase object allows updates;
otherwise 0, indicating either that you passed TRUE in bReadOnly
when you opened the CDatabase object or that the data source itself is read-only.
The data source is read-only if a call to the ODBC API function SQLGetInfo for SQL_DATASOURCE_READ_ONLY returns "y".
这两个函数可以先判断数据库能修改不?如果可以,就执行一个需要的的SQL语句就是了,但是需要注意的就是ExecuteSQL,是会抛出异常的。说到这里,说明一点,如果您老一点不会c++,自然就不知道异常为何物;同样,如果你一点不了解MySql,自然也不会写Sql操作语句了。建议先回去补补,不多,就补补这里就行了。
我们添加一个获取custid的成员函数:
BOOL Cmy_dbDlg::GetCustIdFromEdit(int &out_id) { int cust_id; CString str; const wchar_t *c_str; if(!m_cust_id.GetWindowTextLengthW()) { return false; } m_cust_id.GetWindowTextW(str); c_str = str.GetString(); swscanf_s(c_str, _T("%lu"), &cust_id); out_id = cust_id; return true; }
然后修改AddNew的消息相应函数如下:
void Cmy_dbDlg::OnBnClickedAddNew() { // TODO: Add your control notification handler code here int cust_id = 0 ; CString cust_name; if(!GetCustIdFromEdit(cust_id)) { AfxMessageBox(_T("NULL cust id, return")); return; } if(!m_cust_name.GetWindowTextLengthW()) { AfxMessageBox(_T("NULL cust name, return")); return; } m_cust_name.GetWindowTextW(cust_name); try { CString sql_str; sql_str.Format(_T("insert customer value (%d, '%s')"), cust_id, cust_name); m_db_opr.ExecuteSQL(sql_str); } catch(CDBException* pe) { // The error code is in pe->m_nRetCode pe->ReportError(); pe->Delete(); } }
代码里面最后一段异常捕获代码,会捕获异常的,比如重复插入等。
现在我们尝试插入一个条目:
很明显,插入成功了。上面的画蓝色的圈圈就是了。
当我们再次点击AddNew按钮的时候,捕获异常的部分代码就起作用了:
提示索引重复了。
呵呵,就是这么简单了。
接下来我们修改Edit和Delete事件代码,首先是Edit事件的:
void Cmy_dbDlg::OnBnClickedEdit() { // TODO: Add your control notification handler code here int cust_id = 0 ; CString cust_name; if(!GetCustIdFromEdit(cust_id)) { AfxMessageBox(_T("NULL cust id, return")); return; } if(!m_cust_name.GetWindowTextLengthW()) { AfxMessageBox(_T("NULL cust name, return")); return; } m_cust_name.GetWindowTextW(cust_name); try { CString sql_str; sql_str.Format(_T("update customer set cust_name = '%s' where cust_id = %d"), cust_name, cust_id ); m_db_opr.ExecuteSQL(sql_str); } catch(CDBException* pe) { // The error code is in pe->m_nRetCode pe->ReportError(); pe->Delete(); } }
接着是Delete的:
void Cmy_dbDlg::OnBnClickedDelete() { // TODO: Add your control notification handler code here int cust_id = 0 ; CString cust_name; if(!GetCustIdFromEdit(cust_id)) { AfxMessageBox(_T("NULL cust id, return")); return; } try { CString sql_str; sql_str.Format(_T("delete from customer where cust_id = %d"), cust_id); m_db_opr.ExecuteSQL(sql_str); } catch(CDBException* pe) { // The error code is in pe->m_nRetCode pe->ReportError(); pe->Delete(); } }
这一节说说到这里吧,貌似不能上传附件,如果需要的话,可以邮件我。我方便的时候一起给大家哈。
如果有下一讲:我会讲顶级牛逼的CRecordset这个类,呵呵,更好的数据库操作方式,更好的查询和遍历方式。