sqlite3的C语言使用(一)
前一天我讲了如何在VC中连接sqlite的库,从今天开始就分几个专题详细学习一下sqlite的一些API。当然我也是才接触sqlite3,这些题也都是我的作业题,如果有什么错误大家可以联系我,共同进步。
0.准备工作
在代码头上加上这样一个宏定义:typedef struct sqlite3 sqlite3; 以后我们就可以将sqlite3视为一个新数据类型,表示一个sqlite3数据库句柄。
明确一下今天我们写的这个程序的目的(也就是我的作业题):
通讯录管理软件。 通讯者信息包括:姓名、性别、手机、Email、地址。 软件功能:添加、查询、删除、全部输出。
1.sqlite3_open 打开或新建一个数据库文件
函数原型: int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); |
---|
filename:数据库文件地址
ppDb:sqlite3数据库类型句柄。
函数作用是打开一个数据库文件,如果文件不存在,则创建之。所以我们的程序开头就是:
int _tmain(int argc, _TCHAR* argv[])
{
bool flag = true;
sqlite3 * db;
char szErr[256];
char * pErr;
int n;
int rc = sqlite3_open("addresslist.db",&db);
if (rc != SQLITE_OK)
{
printf("打开数据库出错n");
return 0;
}
2.sqlite3_exec 执行sql语句。(一般用来执行不用返回值的sql语句,如create table、update等)
函数原型 int sqlite3_exec( sqlite3 *, /* An open database */ const char *sql, /* SQL to be evaluated */ int (*callback)(void*,int,char**,char**), /* Callback function */ void *, /* 1st argument to callback */ char **errmsg /* Error msg written here */ ); |
---|
第一个参数是sqlite3数据库句柄,和sqlite3_open函数第2个参数一样。
sql:执行的sql语句。
第三个参数是个回调函数,在执行本函数后会执行回调函数,不用则填NULL。
第四个参数是传给回调函数的参数,不用则填NULL。
errmsg:出错信息,不用则填NULL。
这个函数可以执行一些非查询类的sql语句,很方便。我们在主函数里用sqlite3_exec来创建一个表:
const char * sql = "CREATE TABLE IF NOT EXISTS addlist(
per_id INTEGER PRIMARY KEY,
per_name VARCHAR(16) NOT NULL,
per_sex VARCHAR(2),
per_number VARCHAR(20),
per_email VARCHAR(256),
per_address varchar(256));";
rc = sqlite3_exec(db,sql,NULL,NULL,&pErr);
if (rc != SQLITE_OK)
{
printf("创建表失败n");
return 0;
}
sql语句的意思大家应该都知道,IF NOT EXIST如果表addlist不存在则创建它,当我们第二次运行时执行这个语句也不会再创建表了。
3.接下来就可以等待用户的输入了,我们可以给用户一些选择,比如选1表示要添加联系人,选2表示删除联系人,选3表示查询联系人。这个就一个swich语句完了,我就不发代码了。
再开始写函数,首先是添加联系人的函数AddPerson
void AddPerson(sqlite3 * db)
{
while (getchar() != 'n') ;
char szName[16],szSex[8],szNum[32],szEmail[256],szAddress[256];
printf("输入姓名(回车结束):");
gets(szName);
printf("输入性别(回车结束):");
gets(szSex);
printf("输入电话号码(回车结束):");
gets(szNum);
printf("输入e-mail(回车结束):");
gets(szEmail);
printf("输入地址(回车结束):");
gets(szAddress);
char sql[512];
sprintf(sql,"INSERT INTO addlist VALUES(null,'%s','%s','%s','%s','%s');",
szName,szSex,szNum,szEmail,szAddress);
int rc = sqlite3_exec(db,sql,NULL,NULL,NULL);
if (rc != SQLITE_OK)
{
printf("出错n");
}
return ;
}
没有用新的API,一个sqlite3_exec就解决了问题。
4.sqlite3_prepare 把一条SQL语句编译成字节码留给后面的执行函数(并不执行)
函数原型 int sqlite3_prepare( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); |
---|
db:数据库句柄
zSql:sql语句
nByte:如果nByte小于0,则函数取出zSql中从开始到第一个0终止符的内容;如果nByte不是负的,那么它就是这个函数能从zSql中读取的字节数的最大值。
pzTail:上面提到zSql在遇见终止符或者是达到设定的nByte之后结束,假如zSql还有剩余的内容,那么这些剩余的内容被存放到pZTail中,不包括终止符
ppStmt:能够使用sqlite3_step()执行的编译好的准备语句的句柄,如果错误发生,它被置为NULL,如假如输入的文本不包括sql语句。调用过程必须负责在编译好的sql语句完成使用后使用sqlite3_finalize()删除它。
我们这个函数将sql语句编译成二进制字节码,以便后面的函数使用,编译好的东西就是stmt(第五个参数)。别问我为什么,我也不知道,但要执行sql来查询就要编译。于是我们查询函数SelectPerson可以这么写:
void SelectPerson(sqlite3 * db)
{
char sql[256];
int per_num;
sqlite3_stmt * stmt;
printf("输入要查询的联系人编号:n");
scanf("%d",&per_num);
sprintf(sql,"select * from addlist where per_id='%d'",per_num);
sqlite3_prepare(db,sql,-1,&stmt,NULL);
5.sqlite3_step 执行编译好的sql语句,获得结果的一行
函数原型 int sqlite3_step(sqlite3_stmt*); |
---|
stmt:就是刚才执行sqlite3_prepare后得到的sql语句句柄。
这个函数很简单,执行sql语句,得到返回结果的一行。当然这个得到不是说从返回值得到,而是一个抽象的得到,要真正得到具体数据,还得利用其它函数。
因为是得到返回值的一行,所以说要用循环语句来得到所有行。当然如果只有一行就不用了。我们这里查询某个人的信息,结果应该只有一行,所以执行一次step就行。
这是SelectPerson函数剩下的部分:
if(sqlite3_step(stmt) == SQLITE_ROW)
{
printf("编号:%d 姓名:%s 性别:%s 电话:%s Email:%s 地址:%sn",
sqlite3_column_int(stmt,0),sqlite3_column_text(stmt,1),sqlite3_column_text(stmt,2),
sqlite3_column_text(stmt,3),sqlite3_column_text(stmt,4),sqlite3_column_text(stmt,5));
}
else
{
printf("输入错误n");
}
sqlite3_finalize(stmt);
return;
}
6.如果要查询全部人的数据,sqlite3_step函数就要用while语句来循环读取了,我直接给代码:
void AllSelect(sqlite3 * db)
{
sqlite3_stmt * stmt;
sqlite3_prepare(db,"select * from addlist",-1,&stmt,NULL);
while(sqlite3_step(stmt) == SQLITE_ROW)
{
printf("编号:%d 姓名:%s 性别:%s 电话:%s Email:%s 地址:%sn",
sqlite3_column_int(stmt,0),sqlite3_column_text(stmt,1),sqlite3_column_text(stmt,2),
sqlite3_column_text(stmt,3),sqlite3_column_text(stmt,4),sqlite3_column_text(stmt,5));
}
sqlite3_finalize(stmt);
return ;
}
7.sqlite3_finalize 销毁sql语句句柄。这个函数很简单就不给原型了,记住创建了以后一定要销毁就行。
8.到现在,我们已经完成了3个任务了,添加联系人、查询联系人、列出所有联系人,最后再写一个删除联系人的函数就完成任务了:
void DelPerson(sqlite3 * db)
{
int n;
char sql[256];
printf("输入要删除的联系人编号:");
scanf("%d",&n);
sprintf(sql,"delete from addlist where per_id=%d",n);
int rc = sqlite3_exec(db,sql,NULL,NULL,NULL);
if(SQLITE_OK == rc)
{
printf("执行成功n");
}
else
{
printf("删除失败n");
}
return ;
}
一个sqlite3_exec函数解决问题。
9.总结
这个题目写完了,我也介绍了一些常用的sqlite3的API,并没有想象中那么复杂。这是运行的截图,代码我不发了,如果想要可以联系我。
- 一句代码实现批量数据绑定[上篇]
- 机器学习-从高频号码中预测出快递送餐与广告骚扰
- MS Windows 下基于Atom的LaTeX编译环境的配置
- WCF中的Binding模型之一: Binding模型简介
- WCF中的Binding模型之一: Binding模型简介
- 2017最火的五篇深度学习论文 总有一篇适合你
- SplashScreenSource的妙用
- SplashScreenSource的妙用
- SplashScreenSource的妙用
- Nodejs学习笔记(十七)--- 浮点运算decimal.js
- AI时代让自己幸福更是一种能力
- 持续不断地推荐儿童不宜视频背后,YouTube是这样训练AI的
- 人工智能会导致大量失业,你怕吗
- 机器人产业链分析-中国机器人产业的发展机遇和挑战
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 我的小工具,用C和python实现远程读卡器,远程读写消费卡片
- c语言实现TCP的socket通信
- 多文件目录Makefile的写法
- 一个有趣的例子带你入门canvas
- GitLab 12 跨版本 13 升级
- 【Rust日报】2020-07-28 SO:在命令行下浏览StackOverflow
- 【翻译】200行代码讲透RUST FUTURES (6)
- MPU6050姿态解算方式1-DMP
- 打卡群刷题总结0729——分隔链表
- 单细胞tSNE细胞降维图还可以这样做?!
- 从IIC实测波形入手,搞懂IIC通信
- FreeRTOS例程4-串口DMA收发不定长数据
- FreeRTOS例程3-串口中断接收不定长的数据与二值信号量的使用
- 前端如何将json数据导出为excel文件
- 使用Postman访问腾讯云API3.0