linux下C语言编程操作数据库(sqlite3)

前言:C语言中通过调用 sqlite 的函数接口来实现对数据库的管理(创建数据库、创建表格、插入数据、查询、数据、删除数据等),掌握sqlite数据库的语法,以及sqlite提供的函数接口,那么在linuxC语言编程操作数据库就变得简单了。

 

 

 Centos系统一般默认是没有安装sqlite3数据库的,所以我们要到其官网下载,我下载的版本是 sqlite-3.6.16.tar.gz  

 

[zoulei@CentOS sqlite]$ wget http://www.sqlite.org/sqlite-3.6.16.tar.gz

    进入下载目录,解压文件sqlite-3.6.16.tar.gz解压后生成sqlite-3.6.16目录. cd 进入sqlite-3.6.16

[zoulei@CentOS sqlite]$ tar -xzvf sqlite-3.6.16.tar.gz

[zoulei@CentOS sqlite]$ cd sqlite-3.6.16

[zoulei@CentOS sqlite-3.6.16]$

执行配置脚本,生成相关文件之后使用make命令编译

 

[zoulei@CentOS sqlite-3.6.16]$ ./configure

[zoulei@CentOS sqlite-3.6.16]$ make

[zoulei@CentOS sqlite-3.6.16]$ sudo make install

安装完成之后会在sqlite-3.6.16目录下生成sqlite3等文件

 

看代码:

#include <stdio.h>

#include <stdlib.h>

#include "sqlite3.h"

#define _DEBUG_

int main(int argc, char**argv)

{

     sqlite3 *db=NULL;

     int len;

     int i=0;

     int nrow=0;

     int ncolumn = 0;

     char *zErrMsg =NULL;

     char **azResult=NULL; //二维数组存放结果

     /* 打开数据库 */

     len = sqlite3_open("user",&db);

     if( len )

     {

        /*  fprintf函数格式化输出错误信息到指定的stderr文件流中  */

        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));//sqlite3_errmsg(db)用以获得数据库打开错误码的英文描述。

        sqlite3_close(db);

        exit(1);

     }

     else printf("You have opened a sqlite3 database named user successfully!\n");

 

     /* 创建表 */

     char *sql = " CREATE TABLE SensorData(\

         ID INTEDER PRIMARY KEY,\

         SensorID INTEGER,\

         siteNum INTEGER,\

         Time VARCHAR(12),\

         SensorParameter REAL\

         );" ;

 

      sqlite3_exec(db,sql,NULL,NULL,&zErrMsg);

#ifdef _DEBUG_

      printf("%s\n",zErrMsg);

      sqlite3_free(zErrMsg);

#endif

      /*插入数据  */

      char*sql1 ="INSERT INTO 'SensorData'VALUES(NULL,1,2,201430506201,13.5);";

      sqlite3_exec(db,sql1,NULL,NULL,&zErrMsg);

      char*sql2 ="INSERT INTO 'SensorData'VALUES(NULL,3,4,201530506302,14.5);";

      sqlite3_exec(db,sql2,NULL,NULL,&zErrMsg);

      char*sql3 ="INSERT INTO 'SensorData'VALUES(NULL,5,6,201630506413,18.6);";

      sqlite3_exec(db,sql3,NULL,NULL,&zErrMsg);

 

      /* 查询数据 */

      sql="select *from SensorData";

      sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );

      printf("nrow=%d ncolumn=%d\n",nrow,ncolumn);

      printf("the result is:\n");

      for(i=0;i<(nrow+1)*ncolumn;i++)

        {

          printf("azResult[%d]=%s\n",i,azResult[i]);

        }

 

     /* 删除某个特定的数据 */

      sql="delete from SensorData where SensorID = 1 ;";

      sqlite3_exec( db , sql , NULL , NULL , &zErrMsg );

#ifdef _DEBUG_

      printf("zErrMsg = %s \n", zErrMsg);

      sqlite3_free(zErrMsg);

#endif

 

      /* 查询删除后的数据 */

      sql = "SELECT * FROM SensorData ";

      sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );

      printf( "row:%d column=%d\n " , nrow , ncolumn );

      printf( "After deleting , the result is : \n" );

      for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )

      {

            printf( "azResult[%d] = %s\n", i , azResult[i] );

      }

      sqlite3_free_table(azResult);

#ifdef _DEBUG_

   printf("zErrMsg = %s \n", zErrMsg);

   sqlite3_free(zErrMsg);

#endif

 

      sqlite3_close(db);

      return 0;

 }

 

 代码分析:

其实操作数据库无非就是如何调用sqlite3提供的API,以及如何使用相应的语句操作sqlite3数据库进行增,删,改,查等。那么下面我们着重分析一下sqlite3提供的函数接口。

 

1.打开数据库函数接口

原型:int sqlite3_open(const char * filename, sqlite3 **ppDb);

 

  1. int sqlite3_open(
  2. const char *filename, /* Database filename (UTF-8) */
  1. sqlite3 **ppDb /* OUT: SQLite db handle */
  1. );

用这个函数开始数据库操作。需要传入两个参数,一是数据库文件名,比如:我的虚拟机~/sqlite/路径下的user文件,文件名不需要一定存在,如果此文件不存在,sqlite会自动建立它。如果它存在,就尝试把它当数据库文件来打开。二是sqlite3**,即前面提到的关键数据结构。这个结构底层细节如何,不需要管它。函数返回值表示操作是否正确,如果是SQLITE_OK则表示操作正常。相关的返回值sqlite定义了一些宏。具体这些宏的含义可以参考sqlite3.h 文件。

 

2.关闭数据库函数接口

原型:int sqlite3_close(sqlite3**ppDb);

ppDb为我们使用sqlite3_open()函数打开的数据库链接(对应我写的程序中的db变量)。

 

3.执行sql语句函数接口

原型:int sqlite3_exec(sqlite3*,const char*sql,sqlite_callback,void*data,char**errmsg);

 

 

int sqlite3_exec(

  sqlite3*,                     /* An open database */

  const char *sql,              /* SQL to be executed */

  sqlite_callback,              /* Callback function */

  void *,                       /* 1st argument to callback function */

  char **errmsg                 /* Error msg written here */

);

这就是执行一条sql 语句的函数,

 

第1个参数不再说了,是前面open函数得到的指针。说了是关键数据结构。

第2个参数const char*sql是一条sql 语句,以\0结尾。

第3个参数sqlite3_callback 是回调,当这条语句执行之后,sqlite3会去调用你提供的这个函数。通常设为NULL。

第4个参数void*是你所提供的指针,你可以传递任何一个指针参数到这里,这个参数最终会传到回调函数里面,如果不需要传递指针给回调函数,可以填NULL。

第5个参数char** errmsg 是错误信息。注意是指针的指针。sqlite3里面有很多固定的错误信息。执行sqlite3_exec 之后,执行失败时可以查阅这个指针(直接 printf("zErrMsg = %s \n", zErrMsg)得到一串字符串信息,这串信息告诉你错在什么地方。sqlite3_exec函数通过修改你传入的指针的指针,把你提供的指针指向错误提示信息,这样sqlite3_exec函数外面就可以通过这个char*得到具体错误提示。

 

************************************************************************************************************************

 

说明:通常,sqlite3_callback 和它后面的void*这两个位置都可以填NULL。填NULL表示你不需要回调。比如你做insert 操作,做delete操作,就没有必要使用回调。而当你做select 时,就要使用回调,因为sqlite3 把数据查出来,得通过回调告诉你查出了什么数据。虽然回调显得代码整齐,但有时候你还是想要非回调的select 查询。这可以通过sqlite3_get_table 函数做到。

 

原型:sqlite3_get_table(sqlite3*db,const char*zsql,char***pazResult,int*nrow,int*ncolumn,char**zErrmsg);

 

 

int sqlite3_get_table(

  sqlite3 *db,          /* An open database */

  const char *zSql,     /* SQL to be evaluated */

  char ***pazResult,    /* Results of the query */

  int *pnRow,           /* Number of result rows written here */

  int *pnColumn,        /* Number of result columns written here */

  char **pzErrmsg       /* Error msg written here */

);

void sqlite3_free_table(char **result);

第1个参数不再多说,看前面的例子。

第2个参数是sql 语句,跟sqlite3_exec 里的sql 是一样的。是一个很普通的以\0结尾的char*字符串。

第3个参数是查询结果,它依然一维数组(不要以为是二维数组,更不要以为是三维数组)。它内存布局是:字段名称,后面是紧接着是每个字段值。

第4个参数是查询出多少条记录(即查出多少行,不包括字段名那行)。

第5个参数是多少个字段(多少列)。

第6个参数是错误信息,跟前面一样,这里不多说了。

pazResult返回的字符串数量实际上是(*pnRow+1)*(*pnColumn),因为前(*pnColumn)个是字段名。

 

注意:如果提供 了errmsg,用来创建错误消息的内存是在堆上分布的。 故在调用后,应该检查一下是否为null值,如果有错误发生,使用sqlite3_free()释放errmsg占用的内存。

 

*************************************************************************************************************************************************************************

 

编译运行:

 

[zoulei@CentOS sqlite]$ gcc sqlite.c -o sqlite -l sqlite3

[zoulei@CentOS sqlite]$ ./sqlite

You have opened a sqlite3 database named user successfully!

table SensorData already exists

nrow=3 ncolumn=5

the result is:

azResult[0]=ID

azResult[1]=SensorID

azResult[2]=siteNum

azResult[3]=Time

azResult[4]=SensorParameter

azResult[5]=(null)

azResult[6]=1

azResult[7]=2

azResult[8]=201430506201

azResult[9]=13.5

azResult[10]=(null)

azResult[11]=3

azResult[12]=4

azResult[13]=201530506302

azResult[14]=14.5

azResult[15]=(null)

azResult[16]=5

azResult[17]=6

azResult[18]=201630506413

azResult[19]=18.6

zErrMsg = (null)

row:2 column=5

 After deleting , the result is :

azResult[0] = ID

azResult[1] = SensorID

azResult[2] = siteNum

azResult[3] = Time

azResult[4] = SensorParameter

azResult[5] = (null)

azResult[6] = 3

azResult[7] = 4

azResult[8] = 201530506302

azResult[9] = 14.5

azResult[10] = (null)

azResult[11] = 5

azResult[12] = 6

azResult[13] = 201630506413

azResult[14] = 18.6

zErrMsg = (null)

 

从程序输出结果就可以看出,在删除数据前,我们有三条记录,删除数据后我们发现,数据库内记录少了。从而实现了我们的删除数据目的。

****************************************************************************************************************************************************************************************

 

注意:这里我们可以看到,azResult 的前面 5 个数据正好是我们的表 SensorData 的列属性,之后才是我们要查询的数据。所以我们

 

的程序中才有 i<( nrow + 1 ) * ncolumn  的判断条件:

  for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )

  printf( "azResult[%d] = %s/n", i , azResult[i] );

 

 输出中有 zErrMsg = (null) 这样的字句,这是 zErrMsg 保留的错误信息,正如你所看到的,zErrMsg 为空,表明在执行过程中没有错误信息。

 

***************************************************************************************************************************************************************************

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值