c-mysql(常用)

MySQL C API 使用(基本函数)
liaoxuefeng SQL
了解了以上基础知识,去包装一些函数用来给c使用

accept_mysql 用来连接数据库

MYSQL   accept_mysql()
{
    
    
    MYSQL   mysql;
    if(NULL==mysql_init(&mysql)){
    
    
        err_sys("mysql_init err",__LINE__);
    }
    if(mysql_library_init(0,NULL,NULL)!=0){
    
    
        err_sys("mysql_init err",__LINE__);
    }
    if(NULL==mysql_real_connect(&mysql,"127.0.0.1","root","sss","chatroom",0,NULL,0))
        err_sys("mysql_real_connect",__LINE__);
    if(mysql_set_character_set(&mysql,"utf8")<0)
        err_sys("mysql_set_character_set",__LINE__);
    printf("连接数据库成功\n");
    return  mysql;
}

close_mysql(关闭数据库)


int close_mysql(MYSQL   mysql)
{
    
    
    mysql_close(&mysql);
    mysql_library_end();
    return  0;
}

use_mysql
return 1 代表没数据
return -1 代表mysql语句出错
(用于查询数据库或者修改数据库中的数据,但这个函数的缺点select是只能打印,不能传出单个数据)

int use_mysql(const char*string,MYSQL mysql)
{
    
    
    int i;
    int ret;
    unsigned    int num_fields,num_rows;
    MYSQL mysql_temp=mysql;
    MYSQL_RES  *result=NULL;
    MYSQL_ROW       row;
    MYSQL_FIELD *field;
    ret=mysql_query(&mysql_temp,string);
    if(!ret){
    
    
        result  =   mysql_store_result(&mysql_temp);
        if(result){
    
    
            num_rows=mysql_num_rows(result);
            if(num_rows==0){
    
    
                mysql_free_result(result);
                return  1;
            }        
            num_fields  =mysql_num_fields(result);
            while (field=mysql_fetch_field(result)){
    
    
                printf("%-20s",field->name);
            }
            printf("\n");

            while(row=mysql_fetch_row(result)){
    
    
                for ( i = 0; i < num_fields; i++){
    
    
                    if(row[i]){
    
    
                        printf("%-20s",row[i]);
                    }else{
    
    
                        printf("NULL");
                    }
                }
                printf("\n");
            }
        }else{
    
    
            mysql_free_result(result);
            return  1;
        }
    mysql_free_result(result);
    }
    else{
    
    
    	fprintf(stderr,"query err\n");
        return -1;
    }
    return  0;
}

而如果想要得到select 的每一个数据,我采取的方法是开辟动态内存,但坏处是调用此函数之后要手动free,会很繁琐,而且内存开辟的位置得在函数里面,因为无法确定有多少行结果,同时只有函数返回0或者返回-2的时候要free。调用函数的时候需要if判断。
调用方式

mysqlMsg*mmsglist=NULL;
int mNum=0;
int ret=mysqlGetMsgByUid(mysql,x,&mmsglist,mMum);
if(ret==-2){
    
    
	...
	if(mmsglist!=NULL){
    
    
                free(mmsglist);
                mmsglist=NULL;
      }
}else if(ret==0){
    
    
	...
	if(mmsglist!=NULL){
    
    
                free(mmsglist);
                mmsglist=NULL;
      }
}else{
    
    
	...
}

(如果大家有什么更好的方法可以教教我)

int mysqlGetMsgByUid(MYSQL mysql,int uid,mysqlMsg**mMsgList,int *mNum)
{
    
    
    int i=0;
    int ret;
    unsigned    int num_fields,num_rows;
    MYSQL mysql_temp=mysql;
    MYSQL_RES  *result=NULL;
    MYSQL_ROW       row;
    MYSQL_FIELD *field;
    char table[MYSQL_TABLE_LEN]="message";
    char mysql_order[MYSQL_ORDER_MAXLEN];
    *mNum=0;
    
    snprintf(mysql_order,MYSQL_ORDER_MAXLEN," select id,uid,type,sid,msg,status,flag from %s \
        where uid ='%d' \
        ",table,uid);
    ret=mysql_query(&mysql_temp,mysql_order);
    if(!ret){
    
    
        result  =   mysql_store_result(&mysql_temp);
        if(result){
    
    
            // num_fields  =mysql_num_fields(result);        
            num_rows= mysql_num_rows(result);
            if(num_rows==0){
    
    
                    mysql_free_result(result);
                    return  1;
                }        
            *mNum=num_rows;
            *(mMsgList)=malloc(num_rows*sizeof(mysqlMsg));
            memset(*mMsgList,0,sizeof (num_rows*sizeof(mysqlMsg)));
            while(row=mysql_fetch_row(result)){
    
       
                if((!row[0])||(!row[6])||(!row[1])||(!row[2])||(!row[3])||(!row[4])||(!row[5])){
    
    
                    mysql_free_result(result);
                    fprintf(stderr,"出现 NULL");                    
                    return  -2;
                }
                (*(mMsgList)+i)->id=atoi(row[0]);
                (*(mMsgList)+i)->recv_id=atoi(row[1]);
                (*(mMsgList)+i)->type=atoi(row[2]);
                (*(mMsgList)+i)->send_id=atoi(row[3]);
                strncpy((*(mMsgList)+i)->message,row[4],MYSQL_MSG_SIZE);
                (*(mMsgList)+i)->status=atoi(row[5]);
                (*(mMsgList)+i)->flag=atoi(row[6]);
                // (*(mMsgList)+i)->recv_id=uid;
                i++;
            }
        }else{
    
    
             mysql_free_result(result);
            return  1;
        }
        mysql_free_result(result);
    }else{
    
    
        fprintf(stderr,"???query   fail\n");
        return -1;
    }
    return  0;
}


聊天室里经常用到的mysql语句
增删改查
insert into xxx(name,xxxx,xx)values(xx,xxx,xxxx);
delete from xxx where x=y;
update xxx set x1=y1,x2=y2
select xxx from xx where x= y;

create table
AUTO_INCREMENT 自增
ENGINE=InnoDB 引擎
PRIMARY KEY (id) 主键

NOT NULL 的意义(《mysql必知必会》)

不允许 NULL 值的列不接受该列没有值的行,
换句话说,在插入或更新行时,该列必须有值。

use_mysql("create table account(\
    id BIGINT NOT NULL AUTO_INCREMENT,\
    姓名 varchar(20) NOT NULL ,\
    帐号 varchar(20) NOT NULL UNIQUE,\
    PRIMARY KEY (`id`)\
    )ENGINE=InnoDB 
          AUTO_INCREMENT=1
           DEFAULT CHARSET=utf8",mysql);


在c++中mysql封装成类的确会方便很多,同时它分成了 mysql_noResult_query
,mysql_select_query,mysql_select_SingleLine_query(这个并不必要)三种方式,因为vector,map容器动态扩容的特点,也就不需要上述c版本麻烦的动态内存。

class mysql_db
{
    
    
public:
    mysql_db();
    ~mysql_db();
public:
    /*
        mysql_open()
        return : 1 OK
                -1 失败
     */
    int mysql_open(const char * host, const char * user, const char * password, const char * database, unsigned int port );
    /*
        mysql_noResult_query();
        非select语句查询
        return >0 成功, 为受影响的行数
               -1 失败
     */
    int mysql_noResult_query(const char * sql );
    /*
        mysql_select_query();
        有结果集的查询
        return >0 ok 返回结果集条数
               -1 失败
        map_results first = 行 second = values
        */
    int mysql_select_query(const char * sql, map<int,vector<string>> & map_results);
    /*
        mysql_select_SingleLine_query();
        只有一条数据 , 或者只有一个字段 N 条的查询. 直接调用vector即可
     */
    int mysql_select_SingleLine_query(const char * sql, vector<string> & v_results);
    /*
        mysql_lasterror();
        返回最近一次错误信息
     */
    string mysql_lasterror();
private:
    MYSQL sqlCon;
    MYSQL_RES *m_pResult;
    MYSQL_ROW  m_Row;
};



mysql_db::mysql_db() {
    
    
    mysql_init(&sqlCon);// mysql 初始化
}

mysql_db::~mysql_db() {
    
    
    mysql_close(&sqlCon);// 关闭连接
}

int mysql_db::mysql_open(const char *host, const char *user, const char *password, const char *database,
                         unsigned int port) {
    
    
    char nvalue = 1;
    mysql_options(&sqlCon, MYSQL_OPT_RECONNECT, (char *) &nvalue);// 断线自动重连
    mysql_options(&sqlCon, MYSQL_SET_CHARSET_NAME, "utf8");
    if (!mysql_real_connect(&sqlCon, host, user, password, database, port, NULL, 0)) {
    
    
        return -1;
    }
    return 1;
}

int mysql_db::mysql_noResult_query(const char *sql) {
    
    
    if (mysql_query(&sqlCon, sql) != 0) {
    
    
        return -1;
    }
    return (int) mysql_affected_rows(&sqlCon);
}

int mysql_db::mysql_select_query(const char *sql, map<int, vector<string>> &map_results) {
    
    
    if (mysql_query(&sqlCon, sql) != 0) {
    
    
        return -1;
    }
    if(!(m_pResult = mysql_use_result(&sqlCon))){
    
    
        return -1;
    }
    int i=0;
    int count = mysql_num_fields(m_pResult);
    while(m_Row=mysql_fetch_row(m_pResult)){
    
    
        vector<string>vVal;
        for (int j = 0; j < count; ++j) {
    
    
            if(m_Row[j])
                vVal.push_back(m_Row[j]);
            else
                vVal.push_back("null");
        }
        map_results[i++]=vVal;
    }
    mysql_free_result(m_pResult);
    return i;
}

int mysql_db::mysql_select_SingleLine_query(const char *sql, vector<string> &v_results) {
    
    
    if (mysql_query(&sqlCon, sql) != 0) {
    
    
        return -1;
    }
    if(!(m_pResult = mysql_use_result(&sqlCon))){
    
    
        return -1;
    }
    int count = mysql_num_fields(m_pResult);
    while(m_Row=mysql_fetch_row(m_pResult)){
    
    
        for (int j = 0; j < count; ++j) {
    
    
            v_results.push_back(m_Row[j]);
        }
    }
    mysql_free_result(m_pResult);
    return 0;
}

string mysql_db::mysql_lasterror() {
    
    
    return mysql_error(&sqlCon);
}

关于表怎么设计,我认为聊天室中的我设计的很不好,9张表,由于我的姓名放在account表,我就没去设计如何换姓名。由于密保放在了account表导致群帐号必须重新建表,而不是和人帐号放一起,还得分出文件表和群文件表这导致了程序更加繁琐。
fri_mask表使用来屏蔽好友消息的不知道是不有点鸡肋。。。

虽说第一次设计的不好,但至少程序能跑,而且有了经验,下次就没这么难了。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/adlatereturn/article/details/107281562