赞
踩
前言:C语言中通过调用 sqlite 的函数接口来实现对数据库的管理(创建数据库、创建表格、插入数据、查询、数据、删除数据等),掌握sqlite数据库的语法,以及sqlite提供的函数接口,那么在linux下C语言编程操作数据库就变得简单了。
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等文件
在linux下sqlite3具体怎么操作,可以参考这篇博客:点击打开链接
看代码:sqlite.c
- /*********************************************************************************
- * Copyright: (C) 2017 zoulei
- * All rights reserved.
- *
- * Filename: insert.c
- * Description: This file i
- *
- * Version: 1.0.0(2017年06月22日)
- * Author: zoulei <zoulei121@gmail.com>
- * ChangeLog: 1, Release initial version on "2017年06月22日 19时31分12秒"
- *
- ********************************************************************************/
-
- #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);
- int sqlite3_open(
- const char *filename, /* Database filename (UTF-8) */
- sqlite3 **ppDb /* OUT: SQLite db handle */
- );
用这个函数开始数据库操作。需要传入两个参数,一是数据库文件名,比如:我的虚拟机~/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个参数不再多说,看前面的例子。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 为空,表明在执行过程中没有错误信息。
***************************************************************************************************************************************************************************
遇到的问题:
问题解决:
出现上述问题是因为没有找到库文件的问题。
由于用到了用户自己的库文件,所以应该指明所用到的库,我们可以这样编译:
[zoulei@CentOS sqlite]$ gcc sqlite.c -o sqlite -l sqlite3
通过find命令找出sqlite3依赖的库:
[zoulei@CentOS sqlite-3.6.16]$ find -name "libsqlite3.so"
./.libs/libsqlite3.so
[zoulei@CentOS sqlite-3.6.16]$ cd ./.libs
[zoulei@CentOS .libs]$ ls
所以用 -l sqlite3 选项就可以了(由于编译生成的库文件是 libsqlite3.so.0.8.6 等,去掉前面的lib和后面的版本标志,就剩下 sqlite3 了所以是 -l sqlite3 )
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。