『SQL』SQLite在Visual Studio 2013下的简单使用

什么是SQLite?

SQLite是一个轻量级的数据库,它包含在一个相对小的C库中。它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合。SQLite直接访问其存储文件

SQLite的优点

  • 不需要一个单独的服务器进程或操作的系统(无服务器的)。
  • SQLite不需要配置,这意味着不需要安装或管理。
  • 一个完整的SQLite数据库是存储在一个单一的跨平台的磁盘文件
  • SQLite是非常小的,是轻量级的完全配置时小于400KB,省略可选功能配置时小于250KB
  • SQLite是自给自足的,这意味着不需要任何外部的依赖
  • SQLite事务是完全兼容ACID的允许从多个进程或线程安全访问
  • SQLite支持SQL92(SQL2)标准的大多数查询语言的功能
  • SQLite使用ANSI-C编写的,并提供了简单和易于使用的API
  • SQLite可在UNIX(Linux、Mac OS-X、Android、iOS)和Windows(Win32、WinCE、WinRT)中运行

SQLite的下载

官网下载地址

本篇博客使用的SQLite头文件
提取码:gxlt

本篇博客使用的SQLite动态库
提取码:t35y

注意:本篇博客是在Visual Studio 2013下使用SQLite的教程。

SQLite的配置

  • 下载下来后,全部解压
    在这里插入图片描述
  • 在D盘新建一个文件夹sqlite3
    在这里插入图片描述
  • 打开刚才解压得到的两个文件夹,将sqlite-dll-win32-x86-3290000文件夹中的sqlite3.def和sqlite.dll拷贝到D盘的sqlite3文件夹中,将sqlite-amalgamation-3290000文件夹中的sqlite3.h文件拷贝到D盘的sqlite3文件夹中
    在这里插入图片描述
  • 使用sqlite3.def生成sqlite3.lib文件
lib /out:D:\sqlite3\sqlite3.lib /MACHINE:IX86 /DEF:D:\sqlite3\sqlite3.def

在这里插入图片描述

  • 生成成功
    在这里插入图片描述
  • 最后将sqlite3.lib、sqlite3.dll、sqlite3.h分别拷贝到软件安装目录的lib、bin、include文件夹下
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 使用的SQLite的时候添加下面两条语句即可
    在这里插入图片描述
#include <sqlite3.h>

#pragma comment(lib, "sqlite3.lib")

SQLite测试是否配置成功

  • 首先来创建一个工程,点击新建项目
    在这里插入图片描述
  • 点击VC++,点击空项目,输入项目名称,点击确定
    在这里插入图片描述
  • 右键源文件点击添加新建项
    在这里插入图片描述
  • 选择C++文件,输入名称,点击添加
    在这里插入图片描述
  • 输入以下代码进行测试
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>

#pragma comment(lib,"sqlite3.lib")

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

	rc = sqlite3_open("test.db", &db);

	if (rc){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		exit(0);
	}
	else{
		fprintf(stderr, "Opened database successfully\n");
	}
	sqlite3_close(db);

	system("pause");
	return 0;
}
  • 输出为Opened database successfully表示SQLite配置成功
    在这里插入图片描述

SQLite的使用

继续使用前面测试建立的工程

SQLite的C/C++接口介绍

接口描述
sqlite3_open(const char* filename, sqlite3** ppDb);该例程打开一个指向SQLite数据库文件的连接,返回一个用于其他SQLite程序的数据库连接对象。如果 filename 参数是 NULL 或 ':memory:',那么 sqlite3_open() 将会在 RAM 中创建一个内存数据库,这只会在 session 的有效时间内持续。如果文件名 filename 不为 NULL,那么 sqlite3_open() 将使用这个参数值尝试打开数据库文件。如果该名称的文件不存在,sqlite3_open() 将创建一个新的命名为该名称的数据库文件并打开。
sqlite3_exec(sqlite3*, const char* sql, sqlite_callback, void* data, char** errmsg);该例程提供了一个执行 SQL 命令的快捷方式,SQL 命令由 sql 参数提供,可以由多个 SQL 命令组成。在这里,第一个参数 sqlite3 是打开的数据库对象,sqlite_callback 是一个回调,data 作为其第一个参数,errmsg 将被返回用来获取程序生成的任何错误。sqlite3_exec() 程序解析并执行由 sql 参数所给的每个命令,直到字符串结束或者遇到错误为止。
sqlite3_close(sqlite3*);该例程关闭之前调用 sqlite3_open() 打开的数据库连接。所有与连接相关的语句都应在连接关闭之前完成。如果还有查询没有完成,sqlite3_close() 将返回 SQLITE_BUSY 禁止关闭的错误消息。

Navicat_for_SQLite的安装

介绍SQLite具体使用之前,我们先来安装一个软件,方便查看创建的数据库中的数据
Navicat下载
提取码:r5k9

安装过程

  • 下载下来之后,进行解压
    在这里插入图片描述
  • 进入解压得到的文件夹
    在这里插入图片描述
  • 右键navicat,点击发送到,桌面快捷方式
    在这里插入图片描述
  • 双击桌面图标打开软件,效果如下
    在这里插入图片描述

表的创建

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

#pragma comment(lib,"sqlite3.lib")

int main()
{
	sqlite3 *db;
	char *zErrMsg = 0;
	int  ret;

	// 连接数据库
	ret = sqlite3_open("lab330.db", &db);
	if (ret){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		exit(0);
	}
	else{
		fprintf(stderr, "Opened database successfully\n");
	}

	// SQL语句,创建表
	char* create_tb = "create table student ("\
		"id int unsigned primary key,"\
		"name varchar(20) not null,"\
		"hometown varchar(128) not null"\
		");";

	// 创建表
	ret = sqlite3_exec(db, create_tb, nullptr, nullptr, &zErrMsg);
	if (ret != SQLITE_OK){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	else{
		fprintf(stdout, "Table created successfully\n");
	}

	// 关闭数据库
	sqlite3_close(db);

	system("pause");
	return 0;
}

首先,我们打开项目所在路径,可以看到数据库创建完成
在这里插入图片描述
我们使用Navicat来看一下数据库中表是否创建成功

  • 打开Navicat,点击连接
    在这里插入图片描述
  • 输入连接名(随便取),选择现有的数据库文件,选择数据库文件(刚才新建的数据库文件),点击连接测试
    在这里插入图片描述
  • 点击连接测试后,弹出连接成功,点击确定即可,然后再点击下面的缺点
    在这里插入图片描述
  • 连接上数据库,效果如下
    在这里插入图片描述
  • 点击数据库,看一下其中的数据
    在这里插入图片描述

insert操作

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

#pragma comment(lib,"sqlite3.lib")

int main()
{
	sqlite3 *db;
	char *zErrMsg = 0;
	int  ret;

	// 连接数据库
	ret = sqlite3_open("lab330.db", &db);
	if (ret){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		exit(0);
	}
	else{
		fprintf(stderr, "Opened database successfully\n");
	}

	// SQL语句,创建表
	char* create_tb = "create table student ("\
		"id int unsigned primary key,"\
		"name varchar(20) not null,"\
		"hometown varchar(128) not null"\
		");";

	// 创建表
	ret = sqlite3_exec(db, create_tb, nullptr, nullptr, &zErrMsg);
	if (ret != SQLITE_OK){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	else{
		fprintf(stdout, "Table created successfully\n");
	}

	// SQL语句,插入表
	char* insert_tab = "insert into student values"\
		"(1, 'Fan', 'ShanDong'),"\
		"(2, 'Lin', 'HeBei'),"\
		"(3, 'Niu', 'JiangSu');";

	// 插入数据
	ret = sqlite3_exec(db, insert_tab, nullptr, nullptr, &zErrMsg);
	if (ret != SQLITE_OK){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	else{
		fprintf(stdout, "Table created successfully\n");
	}

	// 关闭数据库
	sqlite3_close(db);

	system("pause");
	return 0;
}

使用Navicat查看表中插入的数据
在这里插入图片描述

update操作

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

#pragma comment(lib,"sqlite3.lib")

int main()
{
	sqlite3 *db;
	char *zErrMsg = 0;
	int  ret;

	// 连接数据库
	ret = sqlite3_open("lab330.db", &db);
	if (ret){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		exit(0);
	}
	else{
		fprintf(stderr, "Opened database successfully\n");
	}

	// SQL语句,创建表
	char* create_tb = "create table student ("\
		"id int unsigned primary key,"\
		"name varchar(20) not null,"\
		"hometown varchar(128) not null"\
		");";

	// 创建表
	ret = sqlite3_exec(db, create_tb, nullptr, nullptr, &zErrMsg);
	if (ret != SQLITE_OK){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	else{
		fprintf(stdout, "Table created successfully\n");
	}

	// SQL语句,插入表
	char* insert_tab = "insert into student values"\
		"(1, 'Fan', 'ShanDong'),"\
		"(2, 'Lin', 'HeBei'),"\
		"(3, 'Niu', 'JiangSu');";

	// 插入数据
	ret = sqlite3_exec(db, insert_tab, nullptr, nullptr, &zErrMsg);
	if (ret != SQLITE_OK){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	else{
		fprintf(stdout, "Table created successfully\n");
	}

	// SQL语句,更新表
	char* update_tab = "update student set name = 'F' where name = 'Fan';"\
		"update student set name = 'L' where name = 'Lin';"\
		"update student set name = 'N' where name = 'Niu';";

	// 更新数据
	ret = sqlite3_exec(db, update_tab, nullptr, nullptr, &zErrMsg);
	if (ret != SQLITE_OK){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	else{
		fprintf(stdout, "Table created successfully\n");
	}

	// 关闭数据库
	sqlite3_close(db);

	system("pause");
	return 0;
}

使用Navicat查看表中的数据
在这里插入图片描述

delete操作

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

#pragma comment(lib,"sqlite3.lib")

int main()
{
	sqlite3 *db;
	char *zErrMsg = 0;
	int  ret;

	// 连接数据库
	ret = sqlite3_open("lab330.db", &db);
	if (ret){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		exit(0);
	}
	else{
		fprintf(stderr, "Opened database successfully\n");
	}

	// SQL语句,创建表
	char* create_tb = "create table student ("\
		"id int unsigned primary key,"\
		"name varchar(20) not null,"\
		"hometown varchar(128) not null"\
		");";

	// 创建表
	ret = sqlite3_exec(db, create_tb, nullptr, nullptr, &zErrMsg);
	if (ret != SQLITE_OK){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	else{
		fprintf(stdout, "Table created successfully\n");
	}

	// SQL语句,插入表
	char* insert_tab = "insert into student values"\
		"(1, 'Fan', 'ShanDong'),"\
		"(2, 'Lin', 'HeBei'),"\
		"(3, 'Niu', 'JiangSu');";

	// 插入数据
	ret = sqlite3_exec(db, insert_tab, nullptr, nullptr, &zErrMsg);
	if (ret != SQLITE_OK){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	else{
		fprintf(stdout, "Table created successfully\n");
	}

	// SQL语句,更新表
	char* update_tab = "update student set name = 'F' where name = 'Fan';"\
		"update student set name = 'L' where name = 'Lin';"\
		"update student set name = 'N' where name = 'Niu';";

	// 更新数据
	ret = sqlite3_exec(db, update_tab, nullptr, nullptr, &zErrMsg);
	if (ret != SQLITE_OK){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	else{
		fprintf(stdout, "Table created successfully\n");
	}

	// SQL语句,删除数据
	char* delete_tab = "delete from student where name = 'L';"\
		"delete from student where name = 'N';";

	// 删除数据
	ret = sqlite3_exec(db, delete_tab, nullptr, nullptr, &zErrMsg);
	if (ret != SQLITE_OK){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	else{
		fprintf(stdout, "Table created successfully\n");
	}

	// 关闭数据库
	sqlite3_close(db);

	system("pause");
	return 0;
}

使用Navicat查看表中数据
在这里插入图片描述

select操作

使用回调函数

首先让我们来了解一下回调函数这个回调函数提供了一个从select语句获得结果的方式。声明如下。

typedef int(*sqlite3_callback)(
	void*,		/* Data provided in the 4th argument of sqlite3_exec() */
	int,		/* The number of columvs in row */
	char**,		/* An array of strings representing fields in the row */
	char**		/* An array of strings representing column names */
	);

如果上面的回调函数在sqlite_exec()程序中作为第三个参数,那么SQLite将为SQL参数内执行的每个select语句中处理的每个记录调用这个回调函数

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

#pragma comment(lib,"sqlite3.lib")

static int callback(void *data, int argc, char **argv, char **azColName){
	int i;
	fprintf(stderr, "%s: \n", (const char*)data);
	for (i = 0; i < argc; i++){
		printf("%s = %s\t\t", azColName[i], argv[i] ? argv[i] : "NULL");
	}
	printf("\n");
	return 0;
}

int main()
{
	sqlite3 *db;
	char *zErrMsg = 0;
	const char* data = "Callback function called";

	// 连接数据库
	sqlite3_open("lab330.db", &db);

	// SQL语句,创建表
	char* create_tb = "create table student ("\
		"id int unsigned primary key,"\
		"name varchar(20) not null,"\
		"hometown varchar(128) not null"\
		");";

	// 创建表
	sqlite3_exec(db, create_tb, nullptr, nullptr, &zErrMsg);

	// SQL语句,插入表
	char* insert_tab = "insert into student values"\
		"(1, 'Fan', 'ShanDong'),"\
		"(2, 'Lin', 'HeBei'),"\
		"(3, 'Niu', 'JiangSu');";

	// 插入数据
	sqlite3_exec(db, insert_tab, nullptr, nullptr, &zErrMsg);

	// SQL语句,更新表
	char* update_tab = "update student set name = 'F' where name = 'Fan';"\
		"update student set name = 'L' where name = 'Lin';"\
		"update student set name = 'N' where name = 'Niu';";

	// 更新数据
	sqlite3_exec(db, update_tab, nullptr, nullptr, &zErrMsg);

	// SQL语句,删除数据
	char* delete_tab = "delete from student where name = 'L';"\
		"delete from student where name = 'N';";

	// 删除数据
	sqlite3_exec(db, delete_tab, nullptr, nullptr, &zErrMsg);

	// SQL语句,查询
	char* select_tab = "select * from student;";

	// 查询
	sqlite3_exec(db, select_tab, callback, (void*)data, &zErrMsg);

	// 关闭数据库
	sqlite3_close(db);

	system("pause");
	return 0;
}

在这里插入图片描述

不使用回调函数

由于查询是一个比较频繁的操作,所以SQLite提供了对表进行查询的接口

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);

上面可以看到,除了查表的接口之外,还有一个释放表的操作,这是为什么呢
这需要我们去看一下sqlite3_get_table的参数列表。第一个参数是打开的数据库的句柄。第二个参数是SQL语句。后面四个参数都是输出型参数,也就是,我们传入一个指针,函数内部完成对它们的赋值。
其中pnROW,pnColumn参数是我们外部开辟好空间,然后传入它们的地址但是pazResult和pzErrmsg参数是我们只是传入一个指针变量(空指针)的地址空间的申请由函数内部动态分配所以pazResult的空间通过调用sqlite3_free_table接口来释放。pzErrmsg的空间通过调用sqlite3_free接口来释放

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

#pragma comment(lib,"sqlite3.lib")

int main()
{
	sqlite3 *db;
	char *zErrMsg = 0;
	const char* data = "Callback function called";

	// 连接数据库
	sqlite3_open("lab330.db", &db);

	// SQL语句,创建表
	char* create_tb = "create table student ("\
		"id int unsigned primary key,"\
		"name varchar(20) not null,"\
		"hometown varchar(128) not null"\
		");";

	// 创建表
	sqlite3_exec(db, create_tb, nullptr, nullptr, &zErrMsg);

	// SQL语句,插入表
	char* insert_tab = "insert into student values"\
		"(1, 'Fan', 'ShanDong'),"\
		"(2, 'Lin', 'HeBei'),"\
		"(3, 'Niu', 'JiangSu');";

	// 插入数据
	sqlite3_exec(db, insert_tab, nullptr, nullptr, &zErrMsg);

	// SQL语句,更新表
	char* update_tab = "update student set name = 'F' where name = 'Fan';"\
		"update student set name = 'L' where name = 'Lin';"\
		"update student set name = 'N' where name = 'Niu';";

	// 更新数据
	sqlite3_exec(db, update_tab, nullptr, nullptr, &zErrMsg);

	// SQL语句,删除数据
	char* delete_tab = "delete from student where name = 'L';"\
		"delete from student where name = 'N';";

	// 删除数据
	sqlite3_exec(db, delete_tab, nullptr, nullptr, &zErrMsg);

	// SQL语句,查询
	char* select_tab = "select * from student;";

	char** result = nullptr;
	int row, col;
	sqlite3_get_table(db, select_tab, &result, &row, &col, nullptr);

	// 结果打印
	for (int i = 0; i <= row; ++i){
		printf("%s\t", result[i * col + 0]);
		printf("%s\t", result[i * col + 1]);
		printf("%s\n", result[i * col + 2]);
	}

	// 空间释放
	sqlite3_free_table(result);

	// 关闭数据库
	sqlite3_close(db);

	system("pause");
	return 0;
}

在这里插入图片描述
看到上面的代码,可能会有疑问,我们使用result接收到的不应该是一个二维数组吗,尤其是我们还传入了row和col来获取它的行数和列数?为什么使用一维数组的方式打印
其实,result获取的是一个一维数组。从参数上可以看出端倪。首先来看char*参数,由于它是一个输出型参数,所以可以去掉一个*,变为char**,由于数组中存的是字符串,所以数组中元素类型为char*,所以可以再去掉一个*,就变成了一个*,所以它只能用来接收一维数组
而且
需要注意的是,我们接收到的row不代表行数,而是实际接收到行数减一的值,所以对表进行遍历时,需要卡范围为[0, row]
还有
接收到的表的内容包含表的字段所在的那一行**,如果不想要字段行,可以将row的范围卡在[1, row]

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值