MT7688學習筆記(5)——OpenWrt下MySQL的使用

Leung_ManWah發表於2018-09-28

一、安裝mysql

1.1 準備資源

下載tar包到目錄dl/
mysql-5.1.73.tar.gz
連結:https://pan.baidu.com/s/1HEAotvd_8SM4IEr03-DeRw 密碼:1yd5
ncurses-5.9.tar.gz
連結:https://pan.baidu.com/s/1rLgoKY9BLGEplIeI8rCjuQ 密碼:c7wp

1.2 編譯安裝

1.cd /work/openwrt-hiwooya-stable-master/
2.make menuconfig
搜尋mysql,找到後打上“*”號


mysql-server的附屬包有:

  • libmysqlclient
  • libncursesw
  • mysql-server
  • uclibcxx
  • libreadline

打上“*”之後開始編譯。

編譯成功後燒進路由器,執行路由器看到/usr/bin下有mysqld這個服務,說明我們已經成功編譯mysql進去了。

1.3 編譯報錯

Package mysql-server is missing dependencies for the following libraries:
libncurses.so.5

未解決。。。

二、配置mysql

2.1 修改存放位置

修改配置檔案 /etc/my.conf ,找到

datadir            =/mnt/data/mysql
tmpdir             =/mnt/data/tmp

更改為你想存放資料庫的地方:

datadir             =/mnt/sda3/data/mysql     #將資料庫放置到U盤對應分割槽上儲存
tmpdir              =/mnt/sda3/data/tmp       #將資料庫臨時資料夾存放到U盤對應分割槽上

2.2 修改資料庫的繫結地址

找到bind-address屬性

bind-address        =127.0.0.1

更改為:

bind-address        =0.0.0.0

修改的目的:允許遠端訪問。

三、初始化及啟動mysql

3.1 初始化mysql

mysql_install_db  --force

3.2 啟動mysql

/etc/init.d/mysqld start

3.3 更改root密碼

mysqladmin -u root password "1234"

3.4 關閉mysqld服務

killall mysqld

四、登入mysql

mysql -u root -p

五、呼叫mysql API

官方文件:https://dev.mysql.com/doc/refman/5.7/en/c-api.html

5.1 標頭檔案

#include <mysql/mysql.h>

5.1 登入MySQL

5.1.1 mysql_init

MYSQL *mysql_init(MYSQL * mysql);
  • 用途:獲取或初始化MYSQL結構
  • 引數:mysql:為NULL,則分配一個(返回其指標)。或按照傳入的結構指標進行初始化。
  • 結果:若為NULL表示出錯。

5.1.2 mysql_options

int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg);
  • 用途:可用於設定額外的連線選項,並影響連線的行為。一次設定一個,可多次呼叫該函式來設定數個選項。
    應在mysql_init()之後、以及mysql_connect()或mysql_real_connect()之前呼叫mysql_options()。
  • 結果:該函式成功時返回0。如果使用了未知選項,返回非0值。

5.1.3 mysql_real_connect

MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, 
                                const char *host,   //MySQL的IP,遠端登入輸入遠端登入的IP地址
                                const char *user,   //登入使用者
                                const char *passwd, //登入密碼
                                const char *db,     //使用的資料庫名稱
                                unsigned int port,  //MySQL埠
                                const char *unix_socket,    //是否使用socket機制登入,NULL:否
                                unsigned long clientflag);  //連線標誌,通常為0
  • 用途:與資料庫建立連線
  • 引數:host:該值必須是主機名或IP地址。如果“host”是NULL或字串"localhost",連線將被視為與本地主機的連線。
    user:引數包含使用者的MySQL登入ID。如果“user”是NULL或空字串"",使用者將被視為當前使用者。在UNIX環境下,它是當前的登入名。
    passwd:引數包含使用者的密碼。如果“passwd”是NULL,僅會對該使用者的(擁有1個空密碼欄位的)使用者表中的條目進行匹配檢查。
    db:是資料庫名稱。如果db為NULL,連線會將預設的資料庫設為該值。
    port:若不是0,其值將用作TCP/IP連線的埠號。
    unix_socket:若不是NULL,該字串描述了應使用的套接字或命名管道。
    client_flag:的值通常為0。
  • 結果:成功返回*mysql指標,失敗返回NULL。

5.1.4 登入資料庫程式碼示例

/**************** 
*SQLBase.h 
*****************/  
class CSQLBase
{
public:
	CSQLBase(string strHost = "127.0.0.1", string strUser = "root", string strPwd = "1234", string strDb = "project");
	virtual ~CSQLBase();

	bool connect(string strHost = "127.0.0.1", string strUser = "root", string strPwd = "1234", string strDb = "project");
	void close(void) ;
	bool query(string strSql) const;
	bool fetchRow(void (*func)(char *row[], void *pAgr), void *pAgr) const;
	
protected:

private:
	MYSQL *m_pMysql;
	string m_strHost;
	string m_strUser;
	string m_strPassword;
	string m_strDatabase;
};

/**************** 
*SQLBase.cpp
*****************/  
#include "SQLBase.h"

CSQLBase::CSQLBase(string strHost, string strUser, string strPwd, string strDb)
{
	this->m_pMysql = mysql_init(nullptr);

	if(this->m_pMysql)
	{
		this->connect(strHost, strUser, strPwd, strDb);
	}
}
CSQLBase::~CSQLBase()
{
	this->close();
}
bool CSQLBase::connect(string strHost, string strUser, string strPwd, string strDb)
{
	this->m_strHost = strHost;
	this->m_strUser = strUser;
	this->m_strPassword = strPwd;
	this->m_strDatabase = strDb;
	if(mysql_real_connect(this->m_pMysql, strHost.c_str(), strUser.c_str(), strPwd.c_str(), strDb.c_str(), 0, nullptr, 0) == nullptr)
	{
		return false;
	}
	mysql_set_character_set(this->m_pMysql, "utf8");
	return true;
}
void CSQLBase::close(void)
{
	if(this->m_pMysql)
	{
		mysql_close(this->m_pMysql);
	}
}

5.2 操作MySQL

5.2.1 mysql_query

int STDCALL mysql_query(MYSQL *mysql,   //MySQL操作結構體
                        const char *q); //操作命令
  • 用途:執行由“Null終結的字串”查詢指向的SQL查詢。正常情況下,字串必須包含1條SQL語句,而且不應為語句新增終結分號(‘;’)或“\g”。如果允許多語句執行,字串可包含多條由分號隔開的語句。
  • 結果:成功返回0,失敗返回1。

5.2.2 mysql_error

const char *mysql_error(MYSQL *mysql);
  • 用途:返回上次呼叫的MySQL函式的錯誤訊息。

5.2.3 mysql_affected_rows

int mysql_affected_rows(MYSQL *mysql);
  • 用途:返回上次UPDATE更改的行數,上次DELETE刪除的行數,或上次INSERT語句插入的行數。對於UPDATE、DELETE或INSERT語句,可在mysql_query()後立刻呼叫。對於SELECT語句,mysql_affected_rows()的工作方式與mysql_num_rows()類似。
  • 結果:大於0的整數表明受影響或檢索的行數。“0”表示UPDATE語句未更新記錄,在查詢中沒有與WHERE匹配的行,或未執行查詢。“-1”表示查詢返回錯誤。

5.2.4 運算元據庫程式碼示例

try
    {
        …………………

        string sql = "SELECT * from zx_users;";
        if (mysql_query(&mysql, sql.c_str()))
        {   
            string err_string = mysql_error(&mysql);

            if(err_string.empty())
                throw string("MySQL query is error!");
            else
                throw err_string;
        }
        ………………
    }
    catch (string &error_msg)
    {
        cout << error_msg << endl;
    }
    catch (...)
    {
        cout << "MySQL operation is error!" << endl;
    }

    mysql_close(&mysql);

5.3 關閉MySQL

5.3.1 mysql_close

void mysql_close(MYSQL *connection);
  • 用途:關閉MySQL資料庫。

5.4 讀取MySQL資料

5.4.1 mysql_use_result

MYSQL_RES *mysql_use_result(MYSQL *mysql);
  • 用途:對於成功檢索資料的每個查詢(SELECT、SHOW、DESCRIBE、EXPLAIN),必須呼叫mysql_store_result()或mysql_use_result()。
    mysql_use_result()將初始化結果集檢索,但並不像mysql_store_result()那樣將結果集實際讀取到客戶端。它必須通過對mysql_fetch_row()的呼叫,對每一行分別進行檢索。這將直接從伺服器讀取結果,而不會將其儲存在臨時表或本地緩衝區內,與mysql_store_result()相比,速度更快而且使用的記憶體也更少。客戶端僅為當前行和通訊緩衝區分配記憶體,分配的記憶體可增加到max_allowed_packet位元組。
    使用mysql_use_result()時,必須執行mysql_fetch_row(),直至返回NULL值,否則,未獲取的行將作為下一個檢索的一部分返回。

5.4.2 mysql_store_result(獲取命令結果)

MYSQL_RES *mysql_store_result(MYSQL *mysql);
  • 用途:mysql_store_result()將查詢的全部結果讀取到客戶端,分配1個MYSQL_RES結構,並將結果置於該結構中。
    如果查詢未返回結果集,mysql_store_result()將返回Null指標(例如,如果查詢是INSERT語句)。
    如果讀取結果集失敗,mysql_store_result()還會返回Null指標。通過檢查mysql_error()是否返回非空字串,mysql_errno()是否返回非0值,或mysql_field_count()是否返回0,可以檢查是否出現了錯誤。
    如果未返回行,將返回空的結果集。(空結果集設定不同於作為返回值的空指標)。
    一旦呼叫了mysql_store_result()並獲得了不是Null指標的結果,可呼叫mysql_num_rows()來找出結果集中的行數。
    可以呼叫mysql_fetch_row()來獲取結果集中的行,或呼叫mysql_row_seek()和mysql_row_tell()來獲取或設定結果集中的當前行位置。
    一旦完成了對結果集的操作,必須呼叫mysql_free_result()。

5.4.3 mysql_fetch_row(讀取資料函式)

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
  • 用途:檢索結果集的下一行。在mysql_store_result()之後使用時,如果沒有要檢索的行,mysql_fetch_row()返回NULL。在mysql_use_result()之後使用時,如果沒有要檢索的行或出現了錯誤,mysql_fetch_row()返回NULL。

5.4.4 mysql_free_result(釋放結果函式)

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
  • 用途:僅需要在考慮到返回很大的結果集時會佔用多少記憶體時呼叫。在指令碼結束後所有關聯的記憶體都會被自動釋放。

5.4.5 讀取資料庫資料程式碼示例

try
    {       
…………………………………

//MySQL命令
        string sql = "SELECT * from zx_users;";
        if (mysql_query(&mysql, sql.c_str()))
        {   
            string err_string = mysql_error(&mysql);

            if(err_string.empty())
                throw string("MySQL query is error!");
            else
                throw err_string;
        }
        cout << "MySQL : " << sql << endl;

        MYSQL_RES *result = mysql_store_result(&mysql);
        if (!result)
            throw string("MySQL not result!");
        //獲取欄位數量
        int num_fields = mysql_num_fields(result);
        if(0 == num_fields)
            throw string("MySQL fields number is 0!");
        //獲取欄位名
        MYSQL_FIELD *fields = mysql_fetch_fields(result);
        if (!fields)
            throw string("MySQL fields fetch is error!");

        for (int i = 0; i < num_fields; i++)
        {
            cout << " " << fields[i].name;
        }
        cout << endl;

        while (MYSQL_ROW row = mysql_fetch_row(result)) //獲取整條資料內容
        {
            for (int i = 0; i < num_fields; i++)
            {
                if (NULL == row[i])
                {
                    cout << " NULL";
                }
                else
                {
                    cout << " " << row[i];
                }   
            }
            cout << endl;
        }

        mysql_free_result(result);

        cout << "MySQL is OK." << endl;
    }
    catch (string &error_msg)
    {
        cout << error_msg << endl;
    }
    catch (...)
    {
        cout << "MySQL operation is error!" << endl;
    }


• 由 Leung 寫於 2018 年 9 月 28 日

• 參考:Openwrt下mysql的使用
    Openwrt下C呼叫mysql API
    MySQL資料庫使用——MySQL在C/C++的API介面
    C API–Linux上C語言讀取MySQL資料庫內容

相關文章