飞鸽传书项目中 sqlite数据库使用ITeye - AG环亚娱乐

飞鸽传书项目中 sqlite数据库使用ITeye

2019年03月13日13时58分52秒 | 作者: 嘉澍 | 标签: 数据库,数据,句子 | 浏览: 717

Sqlite3数据库运用注释

    飞秋项目挨近结尾,各位同学大多数都用的是链表来对上线用户及文件传输来进行数据保存,在开发中选用链表与数据库利害参半,咱们一同先来剖析一下!如有不妥请各位同学弥补!
    首要选用链表不从理论上讲不必与外存进行交互,功率天然相对较高,而数据库在敞开、封闭过程中必定要与外存交互,天然存在着功用距离。
    其次链表存储不会发生锁,可是或许发生数据操作差异,就是一起对一个链表操作时或许发生数据差异,数据库的底层一般会对该机制进行完结,可是在多线程时会发生数据库锁。
    再次在大数据量时链表或许会发生功用瓶颈,而平等数据量下sqlite的数据管理则更为省心。
    在本项目中最重要的一点是选用数据库根本不会呈现段过错,大大提高了开发功率,使数据操作过程变得更为快捷。
   
    数据库的操作从运用方面来总结最常用的主要有六种操作,数据库翻开、封闭,及增修正查操作。

数据库翻开
    数据库在运用过程中必定要留意,数据库中存储二维表,表中存储的是一条一条的记载。
    在我看来,sqlite中数据库是独立的文件,linux版别的没有扩展名约束,在本项目中咱们选用的是feiq.db。这样做的原因是:第一次我树立的数据库叫feiq,生成的可履行文件也叫feiq,编译时文件发生了掩盖。所以最终改成了feiq.db,重现树立的库跟表。
    sqlite3 *db = NULL;
    pthread_mutex_t mutex;//避免数据库死锁
   
    void dbinit()//数据库初始化
    {
        pthread_mutex_init( mutex,NULL);
        sqlite3_open("feiq.db", db);
        if(result!=SQLITE_OK)
        {
            printf("open error\n");
   
        }
    }
    本函数中主要是数据库的初始化,这儿我树立了一个锁,避免数据库死锁,可是不知道是不是真的好使,现在来看是没有什么问题。sqlite3_open("feiq.db", db);句子翻开了数据库,
Feiq.db是数据库文件名,要留意的是运用前先树立数据库 sqlite3 feiq.db,经过create句子树立相应的表:
CREATE TABLE userlist(id integer(4) primary key,name varchar(20),host varchar(30),addr integer(4)) 保存在线用户列表
CREATE TABLE filelist(id integer(4) primary key,name varchar(50),num integer,pkgnum integer(4),size integer(4),ltime integer(4),user varchar(10))保存发送文件列表
CREATE TABLE recvlist(id integer(4) primary key,name varchar(50),num integer,pkgnum integer(4),size integer(4),ltime integer(4),user varchar(10))保存接纳文件列表
CREATE TABLE user(id integer(4) primary key,name char(20),pass char(20)) 保存登陆用户

封闭数据库
void dbclose()//封闭
{
    sqlite3_close(db);
}
在程序完毕后封闭数据库,封闭衔接,开释占用的系统资源。




void dboper(char * sql)//增修正操作
{
    pthread_mutex_lock( mutex);
   
    sqlite3_exec(db,sql,NULL,NULL, errmsg);
    if(errmsg)
    {   
        printf("errsql is %s\n",sql);
        printf("errmsg444=%s \n",errmsg);
    }
   
    pthread_mutex_unlock( mutex);
}
该函数需求一个参数char * sql,这儿传递的是字符指针类型的一个变量,说白了就是传递了一个字符串的首地址,这个字符串是一条sql句子。

在运用过程中实例如下:
在线程启动时初始化数据库,清空用户列表中的一切数据
dbinit();//数据库初始化
dboper("delete from userlist");//先铲除数据库数据
留意 这儿铲除表里的数据一般不会删去表再创立表,用delete from 表名  句子就能够删去指定表中的一切数据。



别的假如sql句子中有变量,
比方:第一次刺进 1,aa,bb
      第2次刺进 2,cc,ff
这儿三个方位的值都是改动的,就需求对sql句子进行拼接

char sql[200] = "";

bzero( sendB, sizeof(sendB));
long seconds = time((time_t*)NULL);
int length = sprintf(sendB, "1:%ld:my:lovecc:%ld:mylovecc", seconds, (IPMSG_ANSENTRY));
sendto(sockfd, sendB, length, 0, (struct sockaddr *) userAddr, sizeof(userAddr));//如有后上线用户播送后进行回复:我在线
   
bzero( sql, sizeof(sql));//sql句子清零
sprintf(sql, "insert into userlist values(null,%s,%s,%d)", username, mathinename, userAddr.sin_addr.s_addr);//sql句子拼接
dboper(sql);//sql句子履行

在sprintf中 insert into userlist values(null,部分是不变的,每次都相同;,%s,%s,%d)"部分%s
%s %d是每次改动的值的方位,所以经过这种办法就能够完结sql句子的拼接。

Insert是刺进句子
Update是修正句子
Delete是查询句子 除了特别运用,如铲除表中一切数据,delete句子后有必要加条件where,否则会清空表数据,在企业级开发中这会形成十分严峻的成果,你就离被开除不远了!


在sql句子中查询句子是最为杂乱的,在实践的java项目开发中一条查询写满一屏幕并不稀罕,所以查询句子极为重要。
int my_print(void *para, int n_column, char **column_value, char **column_name)//回调遍历
{
    int i=0;

    for(i=0;i n_column;i++)
    {
        printf("%s=%s\t",column_name[i],column_value[i]);
    }
    printf("\n");
   
    return 0;
}



void dbquery(char *sql)//查询 显现一切记载
{
    pthread_mutex_lock( mutex);
   
    result = sqlite3_exec(db,sql,my_print,arg, errmsg);
   
    if(errmsg)
    {
        printf("errmsg11=%s \n",errmsg);
    }

    pthread_mutex_unlock( mutex);
}
void dbquery(char *sql)//查询 显现一切记载,相同需求传递一个字符串常量,作为sql句子,运用办法与上边根本共同,所以不再多说。
在这儿有一个回调函数
int my_print(void *para, int n_column, char **column_value, char **column_name)//回调遍历
其作用是每查出来一条记载则调用一次该函数来进行输出,
printf("%s=%s\t",column_name[i],column_value[i]);这儿输出了字段名与字段值
一起该办法是通用的,任何一个表,假如仅仅想按上述格局显现一切的数据的话,直接调用
void dbquery(char *sql)函数,你需求做的就是传入sql句子:"select *from *** where ***=***"

char sql[200] = "";
sprintf(sql ,"select * from userlist where name=%s",name);
dbquery(sql);


查询的别的一种常见用法是将查询到的值取出来,而不仅仅是简略的展现。
在这儿我选用了一个相对变通的办法来取值,不是特别的规范,可是能够完结功用。


void dbquerygetuser(char *sql,IPMSG_USER *user)//依据条件查询用户
{
    pthread_mutex_lock( mutex);

    result = sqlite3_exec(db,sql,my_getuser,user, errmsg);
    if(errmsg)
    {
        printf("errmsg222=%s \n",errmsg);
    }
   
    pthread_mutex_unlock( mutex);
}
这次的回调函数是my_getuser,在下边进行剖析。
result = sqlite3_exec(db,sql,my_getuser,user, errmsg);
本函数传递过来两个参数,一个是前面重复说的sql句子char *sql,这儿需求的是一个查询句子,就是你需求一个什么条件的记载,那么就写sql句子进行查询。my_getuser是指定回调函数。user最为重要,需求传递过来一个结构体目标。

调用时能够:
IPMSG_USER *us = (IPMSG_USER *)malloc(sizeof(IPMSG_USER));
Char sql[200] = "select * from userlist where name=k29";
dbquerygetuser(sql,us);
假如你想用查询到的值 那么printf("getuerbyname %s\n",(*us).name); 就能够了



int my_getuser(void *para, int n_column, char **column_value, char **column_name)//将成果放到user结构体中
{
   
    int i=0;
    char temp[4][100];
    IPMSG_USER *user = (IPMSG_USER *)para;

    for(i=0;i n_column;i++)
    {
        printf("%s=%s\t",column_name[i],column_value[i]);
       
        if(column_value[i]!=NULL)
        {
            strcpy(temp[i],column_value[i]);
            temp[i][strlen(column_value[i])] = \0;
        }
        else
        bzero(temp[i],sizeof(temp[i]));
    }

    printf("\n");

    strncpy((*user).name,temp[1],strlen(temp[1])+1);
    strncpy((*user).host,temp[2],strlen(temp[2])+1);
    (*user).s_addr= (unsigned int)atoi(temp[3]);
   
    return 0;
}

回调函数中被我标示成赤色的部分是我自己想到的一个不规范做法,可是代码彻底能够完结功用。
其意图是要讲查询到的数据放到一个结构体傍边,可是c里边没有iterator目标,也没有其他的辅佐手法,所以这儿我用到了二维字符数组,相当于一个字符串数组,要留意的是不论你表中字段是什么类型,取出来的时分都可所以字符串,所以
for(i=0;i n_column;i++)
    {
        printf("%s=%s\t",column_name[i],column_value[i]);
       
        if(column_value[i]!=NULL)
        {
            strcpy(temp[i],column_value[i]);
            temp[i][strlen(column_value[i])] = \0;
        }
        else
        bzero(temp[i],sizeof(temp[i]));
    }
就取出来了,bzero(temp[i],sizeof(temp[i]));是将为null字段清空bzero
后边再将数组中的数据转化,保存进结构体
strncpy((*user).name,temp[1],strlen(temp[1])+1);
strncpy((*user).host,temp[2],strlen(temp[2])+1);
(*user).s_addr= (unsigned int)atoi(temp[3]);

祝各位好运 呵呵,有问题能够相互评论。

版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表AG环亚娱乐立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章