SQLite库笔记:API函数编程

本文主要介绍SQLite库的一些核心API函数,和实现数据库增删查改功能的C语言示例程序代码。

目录

[1. API函数原型](#1. API函数原型)

[1.1 sqlite3_open](#1.1 sqlite3_open)

[1.2 sqlite3_close](#1.2 sqlite3_close)

[1.3 sqlite3_free](#1.3 sqlite3_free)

[1.4 sqlite3_errmsg](#1.4 sqlite3_errmsg)

[1.5 sqlite3_exec](#1.5 sqlite3_exec)

[1.6 sqlite3_get_table](#1.6 sqlite3_get_table)

[1.7 sqlite3_free_table](#1.7 sqlite3_free_table)

[2. 返回码定义](#2. 返回码定义)

[3. 示例程序](#3. 示例程序)

[3.1 数据库表设计](#3.1 数据库表设计)

[3.2 代码](#3.2 代码)

[3.3 编译运行](#3.3 编译运行)


1. API函数原型

SQLite库有两百多个API,下面列出几个核心的API。

1.1 sqlite3_open

|----------|----------------|----------------|
| 函数声明 | int sqlite3_open(const char *filename, sqlite3 **ppDb); ||
| 描述 | 打开数据库文件 ||
| 参数 | filename[输入] | 数据库文件名 (UTF-8) |
| 参数 | ppDb[输出] | SQLite db句柄 |
| 返回值 | 0-成功,其它-失败 ||

1.2 sqlite3_close

|----------|-----------|---------|
| 函数声明 | int sqlite3_close(sqlite3* pDb); ||
| 描述 | 关闭数据库db句柄 ||
| 参数 | pDb[输入] | 数据库db句柄 |
| 返回值 | 0-成功,其它-失败 ||

1.3 sqlite3_free

|----------|-----------|------|
| 函数声明 | void sqlite3_free(void* ptr); ||
| 描述 | 释放指针数据 ||
| 参数 | Ptr[输入] | 指针数据 |
| 返回值 | 无 ||

1.4 sqlite3_errmsg

|----------|-----------|---------|
| 函数声明 | const char *sqlite3_errmsg(sqlite3* pDb); ||
| 描述 | 获取具体的错误信息 ||
| 参数 | pDb[输入] | 数据库db句柄 |
| 返回值 | 错误信息字符串 ||

1.5 sqlite3_exec

|----------|-----------------|--------------|
| 函数声明 | int sqlite3_exec(sqlite3*db, const char *sql, int (*callback)(void*,int,char**,char**), void *arg, char **errmsg); ||
| 描述 | 运行SQL语句 ||
| 参数 | db[输入] | 一个打开的数据库db句柄 |
| 参数 | Sql[输入] | 要执行的SQL语句 |
| 参数 | callback [输入] | 回调函数 |
| 参数 | arg[输入] | 回调函数的第一个参数 |
| 参数 | errmsg[输出] | 错误信息 |
| 返回值 | 0-成功,其它-失败 ||

1.6 sqlite3_get_table

|----------|-----------------|--------------|
| 函数声明 | int sqlite3_get_table(sqlite3 *db, const char *zSql, char ***pazResult, int *pnRow, int *pnColumn, char **pzErrmsg); ||
| 描述 | 运行SQL查询语句 ||
| 参数 | db[输入] | 一个打开的数据库db句柄 |
| 参数 | zSql[输入] | 要执行的SQL语句 |
| 参数 | pazResult[输出] | 查询的结果 |
| 参数 | pnRow[输出] | 查询结果的行数 |
| 参数 | pnColumn[输出] | 查询结果的列数 |
| 参数 | pzErrmsg[输出] | 错误信息 |
| 返回值 | 0-成功,其它-失败 ||

1.7 sqlite3_free_table

|----------|---------------|-------|
| 函数声明 | void sqlite3_free_table(char **result); ||
| 描述 | 释放SQL查询结果指针 ||
| 参数 | result [输入] | 查询的结果 |
| 返回值 | 无 ||

2. 返回码定义

|---------------------|---------------------|
| sqlite3.h中常遇到的返回码 | 含义 |
| SQLITE_OK (0) | 成功 |
| SQLITE_ERROR (1) | 通用返回码 |
| SQLITE_INTERNAL (2) | 内部故障 |
| SQLITE_PERM (3) | 无法提供新创建的数据库的请求访问模式 |
| SQLITE_ABORT (4) | 操作中断 |
| SQLITE_BUSY (5) | 由于其它数据库连接的并发活动,无法读写 |
| SQLITE_LOCKED (6) | 连接冲突,写操作失败 |

3. 示例程序

3.1 数据库表设计

|----------|----------|-------------|
| 元素 | 类型 | 说明 |
| id | int | 货物ID |
| name | char(16) | 货物名称 |
| supplier | char(16) | 供应商 |
| ymdhms | datetime | 年-月-日 时:分:秒 |
| unit | int | 单价 |
| num | int | 数量 |
| sum | int | 总价 |

3.2 代码

下面的代码实现了数据库的基本功能操作,包括:

  • 创建数据库文件test.db
  • 创建数据库表purchase
  • 向数据库表中插入数据
  • 修改数据库表的数据
  • 删除数据库表中特定ID的数据
  • 查询数据库表中数据条目数量
  • 查询数据库表中所有数据
cpp 复制代码
/*  This is a demo using the SQLite library API functions.
 *  More details about SQLite: https://www.sqlite.org/
 */

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

#define DEBUG_PRINTF(format, ...)   printf("<%s, %d> "format" ", __func__, __LINE__, ## __VA_ARGS__)
#define ARRAY_SIZE(_arr)		    (sizeof((_arr)) / sizeof((_arr)[0]))
#define PURCHASE_DB_FILE			"test.db"

typedef struct _purchase_para{
	int id;
	char name[16];
	char supplier[16];
	char ymdhms[24];
	int unit;
	int num;
	int sum;
}purchase_para;

int iDBInit(sqlite3 **ppDb)
{
	char *err = NULL;
	char sql[256] = {0};
	int ret;

	/* database init */
	ret = sqlite3_open(PURCHASE_DB_FILE, ppDb);
	if (ret != SQLITE_OK) {
		DEBUG_PRINTF("sqlite3_open ret:%d, msg:%s\n", ret, sqlite3_errmsg(*ppDb));
		sqlite3_close(*ppDb);
		return -1;
	}

	snprintf(sql, sizeof(sql), 
		"create table if not exists purchase \
			(id int, \
			name char(16), \
			supplier char(16), \
   			ymdhms datetime,\
			unit int, \
			num int, \
			sum int, \
   			primary key(id, ymdhms));"
		);
	ret = sqlite3_exec(*ppDb , sql , NULL , NULL , &err);
	if (ret != SQLITE_OK) {
		DEBUG_PRINTF("sqlite3_exec ret:%d, %s\n", ret, err);
		sqlite3_free(err);
	}

	return 0;
}

void vDBFree(sqlite3 *pDb)
{
	if (pDb != NULL) {
		sqlite3_close(pDb);
		pDb = NULL;
	}
}

/* insert data */
int iDBInsert(sqlite3 *pDb, purchase_para *pdata)
{
	char sql[256] = {0};
	char *errmsg = NULL;
	int ret;

	if (pDb == NULL || pdata == NULL) {
		return -1;
	}

	snprintf(sql, sizeof(sql), 
			"insert into purchase(id, name, supplier, ymdhms, unit, num, sum) \
			values(%d, '%s', '%s', '%s', %d, %d, %d);", 
			pdata->id, pdata->name, pdata->supplier, pdata->ymdhms, 
			pdata->unit, pdata->num, pdata->sum);

	ret = sqlite3_exec(pDb , sql , NULL , NULL , &errmsg);
	if (ret != SQLITE_OK) {
		DEBUG_PRINTF("sqlite3_exec ret:%d, %s\n", ret, errmsg);
		sqlite3_free(errmsg);
	}
	return ret;
}

/* modify data if id matches */
int iDBUpdateByID(sqlite3 *pDb, purchase_para *pdata)
{
	char sql[256] = {0};
	char *errmsg = NULL;
	int ret;

	if (pDb == NULL || pdata == NULL) {
		return -1;
	}

	snprintf(sql, sizeof(sql), 
		"update purchase set name = '%s', supplier = '%s', ymdhms = '%s', \
        unit = %d, num = %d, sum = %d where id == %d;",
		pdata->name, pdata->supplier, pdata->ymdhms, 
		pdata->unit, pdata->num, pdata->sum, pdata->id);

	ret = sqlite3_exec(pDb , sql , NULL , NULL , &errmsg);
	if (ret != SQLITE_OK) {
		DEBUG_PRINTF("sqlite3_exec ret:%d, %s\n", ret, errmsg);
		sqlite3_free(errmsg);
	}
	return ret;
}

/* delete data if id matches */
int iDBDelByID(sqlite3 *pDb, int id)
{
	int ret = 0;
	char sql[64] = {0};
	char *errmsg = NULL;
	
	if (pDb == NULL) {
		return -1;
	}

	snprintf(sql, sizeof(sql), 
		"delete from purchase where id == %d;vacuum;", id);
	
	ret = sqlite3_exec(pDb , sql , NULL , NULL , &errmsg);
	if (ret != SQLITE_OK) {
		DEBUG_PRINTF("<%s> sqlite3_exec ret:%d, %s\n", __func__, ret, errmsg);
		sqlite3_free(errmsg);
	}
	return ret;
}

/* query the number of database data items */
int iDBQueryCnt(sqlite3 *pDb, int *cnt)
{
	int ret = 0;
	int row = 0;
	int column = 0;
	char **result;
	char sql[64] = {0};
	char *errmsg = NULL;
	
	snprintf(sql, sizeof(sql), "select count(*) from purchase;");

	ret = sqlite3_get_table(pDb , sql , &result , &row , &column , &errmsg);
	if (ret != SQLITE_OK) {
		DEBUG_PRINTF("<%s> sqlite3_exec ret:%d, %s\n", __func__, ret, errmsg);
		sqlite3_free(errmsg);
	}
	else {
		*cnt = atoi(result[1]);
		DEBUG_PRINTF("select successfully, row:%d, col:%d, cnt:%d\n", row, column, *cnt);		
	}
	sqlite3_free_table(result);
	return ret;
}

/* query all data in the database */
int iDBQueryAll(sqlite3 *pDb)
{
	int ret = 0;
	int row = 0;
	int column = 0;
	int i, j;
	char **result;
	char sql[64] = {0};
	char *errmsg = NULL;
	
	snprintf(sql, sizeof(sql), "select * from purchase;");

	ret = sqlite3_get_table(pDb , sql , &result , &row , &column , &errmsg);
	if (ret != SQLITE_OK) {
		DEBUG_PRINTF("<%s> sqlite3_exec ret:%d, %s\n", __func__, ret, errmsg);
		sqlite3_free(errmsg);
	}
	else {
		DEBUG_PRINTF("select successfully, row:%d, col:%d, data:\n", row, column);
		for(i = 0; i <= row; i++)
		{
			for(j = 0; j < column; j++)
			{
				printf("%s, ", result[i * column + j]);
			}
			printf("\n");
		}	
	}
	sqlite3_free_table(result);
	return ret;
}

测试示例

cpp 复制代码
static void vTestInsert(sqlite3 *pDb)
{
	int i;
	int errcnt = 0;
	struct tm *timeinfo = NULL;
	time_t time_now;
	purchase_para data[] = {
		/*{1, "pencil", "sunny", "2024-07-10 12:06:35", 2, 100, 200},*/
		{1, "pencil", "sunny",  "", 2,  100, 200},
		{2, "pen",    "sky",    "", 10, 100, 1000},
		{3, "eraser", "lily",   "", 1,  80,  80},
		{4, "ruler",   "sunny", "", 2,  200, 400},
	};

	time(&time_now);
	timeinfo = localtime(&time_now);

	for(i = 0; i < ARRAY_SIZE(data); i++)
	{
		timeinfo->tm_mon = (timeinfo->tm_mon - i) % 12;
		strftime(data[i].ymdhms, ARRAY_SIZE(data[i].ymdhms), "%Y-%m-%d %H:%M:%S", timeinfo);
		if (iDBInsert(pDb, &data[i]) != 0) {
			errcnt++;
		}
	}
	DEBUG_PRINTF("insert %s\n", (errcnt == 0) ? "succ" : "fail");
}

static void vTestModify(sqlite3 *pDb)
{
	int ret;
	struct tm *timeinfo = NULL;
	time_t time_now;
	purchase_para data = {3, "eraser", "lily", "", 2, 80, 160};

	/* change the ymdhms to the current date and time */
	time(&time_now);
	timeinfo = localtime(&time_now);
	strftime(data.ymdhms, ARRAY_SIZE(data.ymdhms), "%Y-%m-%d %H:%M:%S", timeinfo);

	/* update data */
	ret = iDBUpdateByID(pDb, &data);
	DEBUG_PRINTF("modify %s\n", (ret == 0) ? "succ" : "fail");
}

int main(int argc, char* argv[])
{
	sqlite3 *ptrDb = NULL;
	int cnt = 0;
	int ret;

	if (iDBInit(&ptrDb) != 0) {
		return -1;
	}

	/* Query the number of database data items  */
	iDBQueryCnt(ptrDb, &cnt);
	/* Query all data in the database */
	iDBQueryAll(ptrDb);

	/* Insert some data */
	vTestInsert(ptrDb);
	/* modify data if id=3 */
	vTestModify(ptrDb);
	iDBQueryAll(ptrDb);

	/* delete data if id=4 */
	ret = iDBDelByID(ptrDb, 4);
	DEBUG_PRINTF("delete data %s\n", (ret == 0) ? "succ" : "fail");

	iDBQueryAll(ptrDb);

	vDBFree(ptrDb);
    return 0;
}

3.3 编译运行

将SQLite库编译生成的include和lib文件夹拷贝到工程目录下,编译加上-lsqlite3链接参数。编译示例如下:

运行结果:

相关推荐
向阳1218几秒前
mybatis 动态 SQL
数据库·sql·mybatis
胡图蛋.1 分钟前
什么是事务
数据库
小黄人软件4 分钟前
20241220流水的日报 mysql的between可以用于字符串 sql 所有老日期的,保留最新日期
数据库·sql·mysql
红色的山茶花7 分钟前
YOLOv9-0.1部分代码阅读笔记-loss_tal.py
笔记·深度学习·yolo
张声录19 分钟前
【ETCD】【实操篇(三)】【ETCDCTL】如何向集群中写入数据
数据库·chrome·etcd
无为之士15 分钟前
Linux自动备份Mysql数据库
linux·数据库·mysql
小汤猿人类28 分钟前
open Feign 连接池(性能提升)
数据库
阳冬园1 小时前
mysql数据库 主从同步
数据库·主从同步
车轮滚滚__1 小时前
uniapp对接unipush 1.0 ios/android
笔记
Mr.132 小时前
数据库的三范式是什么?
数据库