您的位置:首页 > 数据库 > MySQL

visual c++ 2008进行MySQL编程(ODBC) --(二) CDatabase操作数据库

2012-05-30 18:38 656 查看
终于他妈可以上图了,唉,继续吧。

本来是想做上下两次说完的,东西太多了,一次写完,我累,看起来也累。
接上一篇文章讲吧,前面说到了具体的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这个类,呵呵,更好的数据库操作方式,更好的查询和遍历方式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: