MT7688学习笔记(5)——OpenWrt下MySQL的使用

一、安装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数据库内容

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容