SQLite3入门学习

本文主要讲解本人在项目中主要用到的一些语句和函数,如需详细了解课前往:SQLite菜鸟教程
使用环境:C和Linux

一、Linux下安装sqlite3

shell脚本安装sqlite3

#!/bin/bash

# library install path
INST_PATH=`pwd`/../install

# set shell script exit when any command failure 
set -e

#define a funciton to build sqlite source code
function build_sqlite()
{
   SRC_NAME=sqlite-autoconf-3380200

   # If source code tarball file not exist, it will download the packet.
   if [ ! -f ${SRC_NAME}.tar.gz ] ; then
      wget https://sqlite.org/2022/${SRC_NAME}.tar.gz
   fi


   # If source code folder not exist, decompress the tarball packet
   if [ ! -d ${SRC_NAME} ] ; then
      tar -xzf ${SRC_NAME}.tar.gz 
   fi

   cd ${SRC_NAME}

   ./configure --prefix=${INST_PATH} --enable-static

   make && make install
}


# call function to start build sqlite

build_sqlite

运行shell 脚本,在Linux命令行执行:bash <该文件名>
set -e 命令用法总结如下:

  1. 当命令的返回值为非零状态时,则立即退出脚本的执行。
  2. 作用范围只限于脚本执行的当前进行,不作用于其创建的子进程。
  3. 另外,当想根据命令执行的返回值,输出对应的log时,最好不要采用set -e选项,而是通过配合exit 命令来达到输出log并退出执行的目的。

二、常用sqlite函数

sqlite3_open

用于打开或创建数据库

sqlite3_open(const char *filename, sqlite3 **ppDb)

该例程打开一个指向 SQLite 数据库文件的连接,返回一个用于其他 SQLite 程序的数据库连接对象。

参数filename:如果 filename 参数是 NULL 或 ‘:memory:’,那么 sqlite3_open() 将会在 RAM 中创建一个内存数据库,这只会在 session 的有效时间内持续。如果文件名 filename 不为 NULL,那么 sqlite3_open() 将使用这个参数值尝试打开数据库文件。如果该名称的文件不存在,sqlite3_open() 将创建一个新的命名为该名称的数据库文件并打开。
参数ppDb:二级指针,指向sqlite3 *db的实例地址(db指向数据库地址,而ppDb指向db的地址)。

sqlite3_exec

用于执行sql语句,进行增删改查等操作

sqlite3_exec(sqlite3 *db, const char *sql, sqlite_callback, void *data, char **errmsg)

第一个参数:为 sqlite3 *db是打开的数据库对象,即指向数据库的指针
第二个参数:需要执行的sqlite语句,例如删除表COMPANY中ID为2的数据: sql = “DELETE from COMPANY where ID=2; SELECT * from COMPANY”
第三个参数:sqlite_callback 是一个回调函数int (callback)(voidpara,int argc,charargv,charargv_name),第二个参数语句执行完的结果可将其丢给这个回调函数处理,注意回调函数的参数类型是不可更改的
第四个参数:data 作为回调函数的第一个参数,它是void *类型的指针,因此它可以转换成任何类型的指针
第五个参数:errmsg 将被返回用来获取程序生成的任何错误
返回值:执行成功返回SQLITE_OK,即为0,否则返回其他值

sqlite3_exec() 程序解析并执行由 sql 参数所给的每个命令,直到字符串结束或者遇到错误为止。

sqlite3_exec回调函数

结合sqlite3_exec函数使用,对每一条查询结果调用一次该回调函数,回调函数里面的程序内容是用户自定义的,不过其参数格式是固定的,如下:

int callback(void*para,int argc,char**argv,char**argv_name)
{
	/*回调函数功能*/
}

argc和argv的作用和main函数的argc和argv的作用类似

第一个参数:void*para是sqlite3_exec传给回调函数的参数
第二个参数:int argc是执行sqlite3_exec的sql语句后sqlite3的shell环境打印的字段数目,即表头的列数
第三个参数char * * argv用于存放字段的值
第四个参数char * * argv_name是字段的名称。

返回值:
1:中断查找
0:继续列举查询到的数据

示例表:

sntimedata
1202133
2202244

对于第一行数据(id = 1):
argc = 3,表示有三个字段,即id、time和data
argv[0] = “1”,argv[1] = “2021”,argv[2] = “33”
argv_name[0] = “id” , argv_name[1] = “time” , argv_name[2] = “data”

sqlite3_close

用于关闭 sqlite3_open() 打开的数据库连接

sqlite3_close(sqlite3*)

所有与连接相关的语句都应在连接关闭之前完成。如果还有查询没有完成,sqlite3_close() 将返回 SQLITE_BUSY 禁止关闭的错误消息。

sqlite3_get_table

int sqlite3_get_table(sqlite3* db,char* order,char* **dResult,int *nRow,int *nColnm,char **errmsg)

//参数释义
/*
db:数据库对象,指向数据库的指针
order:控制语句
**dResult:指针数组,数组的每个存放一个指针,sqlite3_get_table()将数据库里拿出来的数据以字符的方式给dbResult
nRow:查询结果条数
nColnm:每条结果包含多少个数据(字段)
errmsg:报错信息

这个函数的返回值正常是SQLITE_OK(0)
这个函数的报错可以直接打印errmsg。
*/

还是拿这个表做示例,假如test.db数据库里面有个表COMPANY,里面存了以下数据,这时我就可以用sqlite3_get_table()函数来获取里面的内容。

sntimedata
1202133
2202244

通过"select * from COMPANY limit 1;" 获取第一行, 然后给sqlite3_get_table()处理完后,dbResult每个元素对应表里面的值如下:
dbResult[0]~[2]分别代表字段名
dbResult[3]~[5]分别代表第一条记录的值
dbResult[0] = “sn” , dbResult[1] = “time” , dbResult[2] = “data”
dbResult[3] = “1” , dbResult[4] = “2021” , dbResult[5] = “33”
nRow = 1
nColumn = 3
以上值可以直接应用。但是这时如果对dbResult[6]进行访问的话,会出错,因为数组dbResult没有存后面的值。

#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h> 

int main()
{
	 sqlite3 *db;
	 char *errmsg=NULL;    //用来存储错误信息字符串
	 char ret=0;
	 int my_age=0;    //类型根据要提取的数据类型而定
	 char **dbResult; 
	 int nRow=0, nColumn=0;     //nRow  查找出的总行数,nColumn 存储列
	 ret = sqlite3_open("test.db",&db);
	 if(1 == ret)     //数据库创建未成功
	 {
		  fprintf(stderr, "Can't open this database: %s\n", sqlite3_errmsg(db));    //用sqlite3_errmsg()得到错误字符串
		  sqlite3_close(db);
		  return -1;
	 }
	 //获取id=1的那行数据,需要注意的是,sqlite3_get_table获取表的数据总会包括字段名称
	 ret=sqlite3_get_table(db, "select * from COMPANY limit 1;", &dbResult, &nRow, &nColumn, &errmsg);
	 //执行完上面语句后,dbResult里面的值如下:
	 //dbResult[0] = "sn" , dbResult[1] = "time" , dbResult[2] = "data"
	 //dbResult[3] = "1" , dbResult[4] = "2021" , dbResult[5] = "33"
	 //nRow = 1
	 //nColumn = 3
	 if(NULL!=errmsg)
	 {
		  sqlite3_free_table(dbResult);
		  errmsg=NULL;
		  return -1;
	 }
	 my_age = atoi(dbResult[nColumn]);
	 sqlite3_free_table(dbResult);
	 return 0;
}

函数返回值

用于判断函数是否执行成功

#define SQLITE_OK           0   /* Successful result */
/* beginning-of-error-codes */
#define SQLITE_ERROR        1   /* Generic error */
#define SQLITE_INTERNAL     2   /* Internal logic error in SQLite */
#define SQLITE_PERM         3   /* Access permission denied */
#define SQLITE_ABORT        4   /* Callback routine requested an abort */
#define SQLITE_BUSY         5   /* The database file is locked */
#define SQLITE_LOCKED       6   /* A table in the database is locked */
#define SQLITE_NOMEM        7   /* A malloc() failed */
#define SQLITE_READONLY     8   /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT    9   /* Operation terminated by sqlite3_interrupt()*/
#define SQLITE_IOERR       10   /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT     11   /* The database disk image is malformed */
#define SQLITE_NOTFOUND    12   /* Unknown opcode in sqlite3_file_control() */
#define SQLITE_FULL        13   /* Insertion failed because database is full */
#define SQLITE_CANTOPEN    14   /* Unable to open the database file */
#define SQLITE_PROTOCOL    15   /* Database lock protocol error */
#define SQLITE_EMPTY       16   /* Internal use only */
#define SQLITE_SCHEMA      17   /* The database schema changed */
#define SQLITE_TOOBIG      18   /* String or BLOB exceeds size limit */
#define SQLITE_CONSTRAINT  19   /* Abort due to constraint violation */
#define SQLITE_MISMATCH    20   /* Data type mismatch */
#define SQLITE_MISUSE      21   /* Library used incorrectly */
#define SQLITE_NOLFS       22   /* Uses OS features not supported on host */
#define SQLITE_AUTH        23   /* Authorization denied */
#define SQLITE_FORMAT      24   /* Not used */
#define SQLITE_RANGE       25   /* 2nd parameter to sqlite3_bind out of range */
#define SQLITE_NOTADB      26   /* File opened that is not a database file */
#define SQLITE_NOTICE      27   /* Notifications from sqlite3_log() */
#define SQLITE_WARNING     28   /* Warnings from sqlite3_log() */
#define SQLITE_ROW         100  /* sqlite3_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite3_step() has finished executing */
/* end-of-error-codes */

三、常用sqlite语句

SQLite 是不区分大小写的,但也有一些命令是大小写敏感的,比如 GLOB 和 glob 在 SQLite 的语句中有不同的含义,以下语句用于C代码中

获取表COMPANY中的第一条数据

select * from COMPANY limit 1

查找表COMPANY中有多少条数据

SELECT COUNT(*) from COMPANY

删除表COMPANY中第一条数据

DELETE from COMPANY limit 1

向表COMPANY插入数据
例如:向表COMPANY插入3个数据

char  aql_buffer[100];
sprintf(sql_buffer, "INSERT INTO COMPANY VALUES ('%s', '%s', '%s');" , data1, data2,data3);
//sql_buffer是用来存放sql语句的数组,sprintf的作用就是组合sql语句。

创建表COMPANY(包含三个字段SN,DATIME, TEMPERATURE)

CREATE TABLE COMPANY(SN CHAR(10),DATIME CHAR(50),TEMPERATURE CHAR(10))

判断表是否已存在且创建表COMPANY(包含三个字段SN,DATIME, TEMPERATURE),不存在就创建,存在则不做处理

CREATE TABLE if not exists %s(SN CHAR(10),DATIME CHAR(50),TEMPERATURE CHAR(10))

四、常见简单实例

1、连接或创建数据库

下面的C代码用于连接一个现有的数据库。如果数据库不存在,那么它就会被创建,最后将返回一个数据库对象。

#include <stdio.h>
#include <sqlite3.h>

int main(int argc, char* argv[])
{
   sqlite3 *db;//创建指向sqlite数据库的指针db
   char *zErrMsg = 0;//用于存储错误的字符指针
   int rc;//存储sqlite函数返回值

   rc = sqlite3_open("test.db", &db);//打开当前目录的test.db数据库,如果没有就在当前目录创建,并使db指向test.db
	//判断函数是否执行成功
   if( rc )
   {
      printf("Can't open database: %s\n", sqlite3_errmsg(db));
      exit(0);
   }
   else
   {
      printf("Opened database successfully\n");
   }
   sqlite3_close(db);
}

2、创建表

下面C代码在test.db数据库中创建了具有ID,NAME,AGE,ADDRESS,SALARY字段的表

#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h> 

int main(int argc, char* argv[])
{
   sqlite3 *db;
   char *zErrMsg = 0;
   int  rc;
   char *sql;//存放将要执行的sqlite语句

   /* Open database */
   rc = sqlite3_open("test.db", &db);
   if( rc ){
      printf("Can't open database: %s\n", sqlite3_errmsg(db));
      exit(0);
   }else{
      printf("Opened database successfully\n");
   }
   /*创建表COMPANY*/
   sql = "CREATE TABLE COMPANY("  \
         "ID INT PRIMARY KEY     NOT NULL," \//主键,不为空
         "NAME           TEXT    NOT NULL," \//不为空
         "AGE            INT     NOT NULL," \//整型,不为空
         "ADDRESS        CHAR(50)," \//字符类型
         "SALARY         REAL );";

   /* Execute SQL statement */
   rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);//如果不执行回调函数,第三个参数可填0
   if( rc != SQLITE_OK ){
   printf("SQL error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
   }else{
      printf("Table created successfully\n");
   }
   sqlite3_close(db);
   return 0;
}  

3、INSERT 操作

向刚才创建的表插入一条数据。

#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>

int main(int argc, char* argv[])
{
   sqlite3 *db;
   char *zErrMsg = 0;
   int rc;
   char *sql;

   /* Open database */
   rc = sqlite3_open("test.db", &db);
   if( rc ){
      printf("Can't open database: %s\n", sqlite3_errmsg(db));
      exit(0);
   }else{
      printf("Opened database successfully\n");
   }

   /* Create SQL statement */
   sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) "  \
         "VALUES (1, 'Paul', 32, 'California', 20000.00 ); ";//向表COMPANY插入数据

   /* Execute SQL statement */
   rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);
   if( rc != SQLITE_OK ){
      printf("SQL error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
   }else{
      printf("Records created successfully\n");
   }
   sqlite3_close(db);
   return 0;
}

4、SELECT操作

查找数据库中表的数据

#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>

/*回调函数:进一步处理sqlite3_exec函数的返回结果,并打印参数data传入的值*/
static int callback(void *data, int argc, char **argv, char **azColName){
   int i;
   printf("%s: ", (const char*)data);
   for(i=0; i<argc; i++){
      printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");//打印每一行中的每个字段值,即每一行中的每一列的值
   }
   printf("\n");
   return 0;
}

int main(int argc, char* argv[])
{
   sqlite3 *db;
   char *zErrMsg = 0;
   int rc;
   char *sql;
   const char* data = "Callback function called";//用于传给回调函数的第一个参数

   /* Open database */
   rc = sqlite3_open("test.db", &db);
   if( rc ){
      printf("Can't open database: %s\n", sqlite3_errmsg(db));
      exit(0);
   }else{
      printf("Opened database successfully\n");
   }

   /* Create SQL statement */
   sql = "SELECT * from COMPANY";//查询COMPANY表中的所有数据

   /* Execute SQL statement */
   rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
   if( rc != SQLITE_OK ){
      printf("SQL error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
   }else{
      printf("Operation done successfully\n");
   }
   sqlite3_close(db);
   return 0;
}

5、DELETE 操作

对数据库的表进行数据删除操作

#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h> 

int main(int argc, char* argv[])
{
   sqlite3 *db;
   char *zErrMsg = 0;
   int rc;
   char *sql;
   const char* data = "Callback function called";

   /* Open database */
   rc = sqlite3_open("test.db", &db);
   if( rc ){
      printf("Can't open database: %s\n", sqlite3_errmsg(db));
      exit(0);
   }else{
      printf("Opened database successfully\n");
   }

   /* Create merged SQL statement */
   sql = "DELETE from COMPANY where ID=2; ";//删除表COMPANY中ID=2的行

   /* Execute SQL statement */
   rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);
   if( rc != SQLITE_OK ){
      printf("SQL error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
   }else{
      printf("Operation done successfully\n");
   }
   sqlite3_close(db);
   return 0;
}

6、判断表是否空

方法1:我将代码封装成了一个函数,用来判断表是否为空格,函数的参数为表名和数据库对象(指向数据库的指针),如果该表不为空则返回1,如果为空则返回0;

int determine_table_exist(char *table_name, sqlite3 *db)
{
	char 	sendata_buffer2[100];
	int 	rc =-1;
	char 	*zErrMsg = 0;
	char 	**dbResult;
	int 	nRow = 0, nColumn = 0;

	memset(sendata_buffer2, 0, sizeof(sendata_buffer2));
	sprintf(sendata_buffer2, "select * from %s limit 1", table_name);
	rc = sqlite3_get_table(db, sendata_buffer2, &dbResult, &nRow, &nColumn, &zErrMsg);
	if(rc != SQLITE_OK)
	{
		printf("Execute sqlite3_get_table failure:%s\n", zErrMsg);
		sqlite3_free(zErrMsg);
		exit(0);
	}
	return nRow;
}

方法2:用回调函数,查询表的数据总项数,并返回。


/*Determines whether the table is empty*/
int  empty_table_determine(char *table_name)
{
	char 	sql[100];
	int 	rc =-1;
	char 	*zErrMsg = 0;
	int  	result = 0;

	sprintf(sql, "SELECT COUNT(*) from %s", table_name);

	rc = sqlite3_exec(db, sql, callback_sql, &result, &zErrMsg);
   	if( rc != SQLITE_OK )
   	{
      	printf("table_sql: %s\n", zErrMsg);
     	sqlite3_free(zErrMsg);
  	}
  	else
   	{
		return result;
   	}
}

static int callback_sql(void *data, int argc, char **argv, char **azColName)
{
	*(int *)data = atoi(argv[0]);
	return 0;
}

7、判断表是否存在

/*Determines whether the table exists*/
int determine_table_exist(char *table_name)
{
	char 	table_exist[512];
	int 	rc =-1;
	char 	*zErrMsg = 0;
	int		result = 0;

	sprintf(table_exist, "SELECT COUNT(*) FROM sqlite_master where type ='table' and name ='%s';", table_name);
	rc = sqlite3_exec(db, table_exist, table_exist_callback, &result, &zErrMsg);
	if(rc != SQLITE_OK)
	{
		printf("sqlite_table_exist:%s\n", zErrMsg);
		sqlite3_free(zErrMsg);
		exit(0);
	}
	
	if(result)
	{
		syslog(LOG_NOTICE, "%s is exist!\n", table_name);
		return result;
	}
	else
	{
		return result;
	}
}

static int table_exist_callback(void *data, int argc, char **argv, char **azColName)
{
    if ( 1 == argc)
  	{
		*(int *)data = atoi(*(argv));
  	}
  	return 0; 
}

参考链接:
https://www.runoob.com/sqlite/sqlite-tutorial.html
https://www.cnblogs.com/zxc2man/p/7463455.html
https://blog.51cto.com/u_15197573/2772313

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值