本文主要介绍SQLite库的一些核心API函数,和实现数据库增删查改功能的C语言示例程序代码。
目录
1. API函数原型
1.1 sqlite3_open
1.2 sqlite3_close
1.3 sqlite3_free
1.4 sqlite3_errmsg
1.5 sqlite3_exec
1.6 sqlite3_get_table
1.7 sqlite3_free_table
2. 返回码定义
3. 示例程序
3.1 数据库表设计
3.2 代码
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的数据
- 查询数据库表中数据条目数量
- 查询数据库表中所有数据
/* 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;
}
测试示例
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链接参数。编译示例如下:
运行结果: