MySQL數(shù)據(jù)庫接口的VC實現(xiàn)與應(yīng)用(2)

字號:

3 利用MySQL自帶的C API函數(shù)實現(xiàn)數(shù)據(jù)庫功能調(diào)用
    由于各個數(shù)據(jù)庫之間的差異,它們所提供的數(shù)據(jù)庫功能也就各有不同。這樣,通過ODBC API就不可能完全擁有所有的數(shù)據(jù)庫功能,因而影響了程序?qū)?shù)據(jù)庫的控制功能,也就不能充分發(fā)揮數(shù)據(jù)庫的能力。并且這種統(tǒng)一的接口還是以損失效能為前提的,這就使數(shù)據(jù)庫操作時間延長。所以,為了解決以上問題,MySQL的制造商在提供ODBC驅(qū)動程序的基礎(chǔ)上,還提供了各種編程環(huán)境下的API,其中包括C API。這些API函數(shù)很顯然能盡可能地發(fā)揮數(shù)據(jù)庫的能力,并減少數(shù)據(jù)庫操作的延長時間,但卻使程序的通用性受到嚴(yán)重影響。
    MySQL提供了一套C API函數(shù),它由一組函數(shù)以及一組用于函數(shù)的數(shù)據(jù)類型組成,這些函數(shù)與MySQL 服務(wù)器進行通信并訪問數(shù)據(jù)庫,可以直接操控數(shù)據(jù)庫,因而顯著地提高了操控效能。
    C API數(shù)據(jù)類型包括:MYSQL(數(shù)據(jù)庫連接句柄)、MYSQL_RES(查詢返回結(jié)果集)、MYSQL_ROW(行集)、MYSQL_FIELD(字段信息)、MYSQL_FIELD_OFFSET(字段表的偏移量)、my_ulonglong(自定義的無符號整型數(shù))等;C API提供的函數(shù)包括:mysql_close()、mysql_connect()、mysql_query()、mysql_store_result()、mysql_init()等,其中mysql_query()最為重要,能完成絕大部分的數(shù)據(jù)庫操控。
    下面將具體討論數(shù)據(jù)庫操作類CDatabase通過C API的實現(xiàn)以及在VC中的應(yīng)用。
    3.1 CDatabase類的實現(xiàn)
    CDatabase類封裝了MySQL數(shù)據(jù)庫的功能,因此不具備通用性,只能在對MySQL的應(yīng)用程序中使用。下面將根據(jù)C++要求及規(guī)范給出CDatabase類的具體結(jié)構(gòu)以及相關(guān)簡要介紹:
    class CDatabase
    {
    public:
    BOOL UnLockTable(); //解鎖
    BOOL LockTable(char* TableName,char* PRIORITY); //加鎖
    int Reload(); //重新登陸,非零時返回錯誤信息
    char* GetState(); //服務(wù)器狀態(tài)
    char* GetServerInfo(); //服務(wù)器信息
    int GetProtocolInfo(); //協(xié)議信息
    char* GetHostInfo(); //主機信息
    char * GetClientInfo(); //客戶機信息
    char* GetFieldName(int FieldNum); //字段名
    BOOL IsEnd(); //是否最后
    int DropDB(char *db); //刪除數(shù)據(jù)庫,非零時返回錯誤信息
    void SeekData(int offset); //查找指定數(shù)據(jù)
    int CreateDB(char *db); //創(chuàng)建數(shù)據(jù)庫,非零時返回錯誤信息
    void FreeRecord(); //釋放結(jié)果集
    unsigned int GetFieldNum(); //得到字段數(shù)
    BOOL ConnectDB(Database_Param *p); //連接數(shù)據(jù)庫
    MYSQL_ROW GetRecord(); //得到結(jié)果(一個記錄)
    my_ulonglong GetRowNum(); //得到記錄數(shù)
    BOOL SelectDB(Data_Param *para); //選擇數(shù)據(jù)庫
    BOOL UpdateRecord(Data_Param *para); //更新記錄
    BOOL SelectRecord(Data_Param *para); //選擇記錄
    BOOL InsertRecord(Data_Param *para); //插入記錄
    BOOL DelRecord(Data_Param *para); //刪除記錄
    BOOL SelectAll(Data_Param *para); //選擇所有記錄
    char * OutErrors(); //輸出錯誤信息
    CDatabase(); //初始化數(shù)據(jù)庫
    virtual ~CDatabase(); //關(guān)閉數(shù)據(jù)庫連接
    private:
    MYSQL mysql; //數(shù)據(jù)庫連接句柄
    MYSQL_RES *query; //結(jié)果集
    MYSQL_ROW row; //記錄集
    MYSQL_FIELD *field; //字段信息(結(jié)構(gòu)體)
    BOOL FindSave(char *str); //查找并保存結(jié)果集
    };
    通過CDatabase類中定義的這些功能函數(shù),我們可以通過遠(yuǎn)程或本機完成對MySQL數(shù)據(jù)庫的絕大部分操控,并且由于定義了解鎖和加鎖功能,使得應(yīng)用程序能夠多線程或多進程地訪問數(shù)據(jù)庫,大大提高了效能。以上函數(shù)的具體功能都是通過調(diào)用C API函數(shù)實現(xiàn)的。
    3.2 CDatabase類在VC中的應(yīng)用
    第一步 建立初始化MySQL對象,并且將其初始化。即定義CDatabase類對象,這樣程序就會自動調(diào)用構(gòu)造函數(shù)CDatabase(),完成初始化。
    構(gòu)造函數(shù)實現(xiàn)如下:
    CDatabase::CDatabase ()
    {
    mysql_init (&mysql);
    }
    完成初始化只需定義CDatabase類對象,即
    CDatabase base;
    第二步 連接服務(wù)器,并連接需要的數(shù)據(jù)庫。即調(diào)用ConnectDB(Database_Param *p)函數(shù),結(jié)構(gòu)體Database_Param中存放數(shù)據(jù)庫參數(shù),包括主機名、用戶名、密碼、數(shù)據(jù)庫名等。該函數(shù)如返回TRUE表示連接成功,否則表示失敗。
    連接函數(shù)實現(xiàn)如下:
    BOOL CDatabase::ConnectDB(Database_Param *p)
    {
    if(!mysql_real_connect(&mysql,p->host,p->user,p->password,p->db,p->port,p->unix_socket,p->client_flag))
    {
    OutErrors(); // 輸出錯誤信息
    return false;
    }
    return true;
    }
    第三步 對數(shù)據(jù)庫進行加鎖。即調(diào)用LockTable(char* TableName,char* PRIORITY),對相應(yīng)的表TableName完成相應(yīng)屬性PRIORITY的加鎖,使程序兼容多線程功能。 加鎖函數(shù)實現(xiàn)如下:
    BOOL CDatabase::LockTable(char* TableName,char* PRIORITY)
    {
    char str[50];
    sprintf(str,"LOCK TABLES %s %s",TableName,PRIORITY);
    if(mysql_query(&mysql,str))
    return false;
    return true;
    }
    第四步 完成數(shù)據(jù)庫操作。即根據(jù)需要調(diào)用UpdateRecord(Data_Param *para)、SelectRecord(Data_Param *para)、InsertRecord(Data_Param *para)、DelRecord(Data_Param *para)等操作。其中的結(jié)構(gòu)體Data_Param中存放數(shù)據(jù)庫操作參數(shù)。上述兩個結(jié)構(gòu)體的定義在global.h中。 InsertRecord函數(shù)實現(xiàn)如下,其它實現(xiàn)方法相似:
    BOOL CDatabase::InsertRecord(Data_Param *para)
    {
    char str[80];
    sprintf(str,"insert into %s values(%s)",para->tab_name,para->insert_val);
    if(mysql_query(&mysql,str))
    return false;
    return true;
    }
    第五步 解鎖數(shù)據(jù)庫。即調(diào)用UnLockTable(),完成對上述被加鎖的表的解鎖。 解鎖函數(shù)實現(xiàn)如下:
    BOOL CDatabase::UnLockTable()
    {
    if(mysql_query(&mysql,"UNLOCK TABLES"))
    return false;
    return true;
    }
    第六步 關(guān)閉數(shù)據(jù)庫連接。即調(diào)用析構(gòu)函數(shù)~CDatabase(),關(guān)閉數(shù)據(jù)庫,并自動釋放初始化時定義的CDatabase類對象。 析構(gòu)函數(shù)如下:
    CDatabase::~CDatabase()
    {
    if(query)
    mysql_free_result(query);
    mysql_close(&mysql);
    }
    注意:在編譯程序時,必須加入MySQL的庫文件libmySQL.lib。