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

 

终于他妈可以上图了,唉,继续吧。

 

本来是想做上下两次说完的,东西太多了,一次写完,我累,看起来也累。

接上一篇文章讲吧,前面说到了具体的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基于对话框的工程,我们要做上面说的一些操作数据库的编码操作了:

visual c++ 2008进行MySQL编程(ODBC) --(二) CDatabase操作数据库_第1张图片

 创建一个纯种的对话框,呵呵:

visual c++ 2008进行MySQL编程(ODBC) --(二) CDatabase操作数据库_第2张图片

生成的dialog,我们添加我们要的东西:

visual c++ 2008进行MySQL编程(ODBC) --(二) CDatabase操作数据库_第3张图片

 

现在查看一下类视图,可以看到如下:

visual c++ 2008进行MySQL编程(ODBC) --(二) CDatabase操作数据库_第4张图片

 

我要做的操作,都是在类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:


visual c++ 2008进行MySQL编程(ODBC) --(二) CDatabase操作数据库_第5张图片

visual c++ 2008进行MySQL编程(ODBC) --(二) CDatabase操作数据库_第6张图片

上图是添加cust id,添加cust name一致。

接下来,给addnew这个按钮添加单击事件:

visual c++ 2008进行MySQL编程(ODBC) --(二) CDatabase操作数据库_第7张图片

visual c++ 2008进行MySQL编程(ODBC) --(二) CDatabase操作数据库_第8张图片

上图中,我们添加消息响应函数为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();
    }
}

代码里面最后一段异常捕获代码,会捕获异常的,比如重复插入等。

现在我们尝试插入一个条目:

visual c++ 2008进行MySQL编程(ODBC) --(二) CDatabase操作数据库_第9张图片

查看数据库,就发现已经有插入的条目了:

visual c++ 2008进行MySQL编程(ODBC) --(二) CDatabase操作数据库_第10张图片

很明显,插入成功了。上面的画蓝色的圈圈就是了。

当我们再次点击AddNew按钮的时候,捕获异常的部分代码就起作用了:

visual c++ 2008进行MySQL编程(ODBC) --(二) CDatabase操作数据库_第11张图片

提示索引重复了。

呵呵,就是这么简单了。

接下来我们修改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这个类,呵呵,更好的数据库操作方式,更好的查询和遍历方式。

 


 

你可能感兴趣的:(sql,编程,C++,mysql,数据库)