关系型数据库-sqlite3(c/c++的API接口)
关系型数据库-sqlite3(c/c++的API接口)
·
数据库对c/c++的API接口
DB数据库本质只是一些用户的数据 通过DBMS去管理用户数据 而DBMS是通过SQL语句去控制的 之前我们都是在终端上输入SQL语句
接下来我们需要学会如何在代码中去控制DBMS
sqlite3的API接口的核心部分:
两大对象
八大函数
两大对象
数据库连接对象(表示你要操作哪个数据库)
数据库连接句柄/相当于数据库的文件描述符
sqlite3 * 代表你打开的按个sqlite3的数据库文件(test.db)
后续对数据库的操作都需要使用到该对象
SQL语句对象
就是一条准备好的SQL语句
操作数据库的标准语言就是SQL语句 在这里就是使用准备好的SQL语句对象去操作数据库连接对象表示的数据库
八大函数
在函数中操作sqlite3数据库的流程:
1.打开数据库 建立连接
sqlite3_open();
打开或者创建一个sqlite3数据库 返回一个数据库的连接对象 (sqlite3 * )
2.操作数据库
sqlite3_prepare_*() //准备好一个SQL语句
sqlite3_bind_*() //函数族 绑定参数
sqlite3_step() ;//执行准备好的SQL语句
sqlite3_column() ;//输出查询到的数据库的数据
sqlite3_finalize() ; //是否资源 销毁SQL语句对象
sqlite3_exec() ;
3. 关闭数据库
sqlite3_close() ;//关闭数据库连接对象
具体的API函数解析:
(1)打开一个sqlite3的数据库连接对象
SQLITE_API int sqlite3_open
(
const char *filename, //你要打开的数据库的路径名
sqlite3 **ppDb //二级指针 用来保存打开的数据库连接对象
);
sqlite3* 用来表示你打开的那个sqlite3的数据库文件(test.db) 后续对数据库的所有操作都是通过该文件。
返回值:
成功返回SQLITE_OK
失败返回其他值
(2)关闭数据库连接对象
SQLITE_API int sqlite3_close(sqlite3*);
参数表示你要关闭哪个打开的数据库连接对象
(3)准备好一个SQL语句对象
使用sqlite3_stmt这个结构来描述一个准备好的SQL语句对象
我们的应用都是通过SQL语句对象去发送SQL指令
SQLITE_API int sqlite3_prepare_v2
(
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 */
);
函数功能: 把一个字符串类型的SQL语句命令转换成可以使用的语句对象类型sqlite3_stmt
参数列表:
db: 数据库连接对象 表示你得语句将要作用在哪一个数据库上
zSql: 你要执行的SQL语句的字符串格式
nByte:SQL语句的长度 或者是 你要编译到zSql字符串的哪一个位置
原始的数据库字符串zSql有可能包含多条SQL语句
>0 编译到zSql指向的sql语句的前nBytes个字节
<0 编译到zSql指向的sql语句的第一个'\0'为止
=0 什么都不编译
ppStmt:二级指针 用来保存编译好后的SQL语句对象
pzTail :指向原始SQL语句字符串zSql中未使用的部分 一般给0 或者NULL
返回值:
成功返回SQLITE_OK
失败返回其他值
(4) 执行准备好的SQL语句对象
SQLITE_API int sqlite3_step(sqlite3_stmt*);
成功返回SOLITE_DONE
失败返回其他值
参数就是你要执行的SQL语句对象
(5) 释放语句对象资源
SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
一般情况下 先编译sql语句再执行sql语句 但是编译的过程需要销毁资源 如果需要插入1000条记录
需要编译1000次 然后执行1000次 --》效率太低
那么我们可以在使用类似的sql语句时,先编译一次语句,只改变参数/变量,执行1000次
参数怎么表示?
"insert into class1 values(参数名, 参数名, 参数名, 参数名);"
:xxx 就是一个sql语句中的参数 xxx一般就是一个变量
@xxx
$xxx
int num;
char name[256]={0};
float score;
int tel;
char sql[]="insert into class1 values(:num , :name, :score, :tel);" //占位符
对该sql语句只需要编译一次即可 每次运行之前都需要对四个参数进行绑定(为他赋值)
绑定参数相关函数
(1)获取参数在原始sql语句中的下标/索引
SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt* pstmt, const char *zName);
参数:
pstmt: sql语句对象的指针
zname: 参数名
返回值:
返回该参数在sql语句中的下标
如果没有该参数就返回0
(2)给该参数绑定值(不同的参数根据他的类型调用下面不同的函数进行绑定)
SQLITE_API int sqlite3_bind_int(sqlite3_stmt* pstmt, int index , int value);
参数:
第一个参数: sql语句对象的指针
第二个参数: 该参数在sql语句对象中的索引/下标
第三个参数: 要给参数绑定的值
SQLITE_API int sqlite3_bind_text(sqlite3_stmt*pstmt,int index,const char* value,int len,void(*func)(void*));
参数:
第一个参数: sql语句对象的指针
第二个参数: 该参数该sql语句对象中的下标
第三个参数: 要给这个参数绑定的那一个字符串的首地址
第四个参数: 第三个参数表示的字符串的长度 防止越界
第五个参数: 函数指针 指向一个函数 该函数用于释放values指向的字符串的空间 如果不需要就填NULL
代码实现:
#include <stdio.h>
#include <string.h>
#include <sqlite3.h>
//编译的时候需要加上 -lsqlite3
int main(int argc,char * argv[])
{
//创建一个数据库连接对象的指针
sqlite3 *pdb;
//打开一个数据库连接对象
int ret=sqlite3_open(argv[1],&pdb);
if(ret!=SQLITE_OK)
{
perror("sqlit3_open error\n");
return -1;
}
//创建一个sql语句对象的指针
sqlite3_stmt * pstmt;
const char * sql = "insert into student values(@id,@name,@score);";
ret = sqlite3_prepare_v2(pdb,sql,-1,&pstmt,NULL);
if(ret != SQLITE_OK)
{
perror("sqlite3_prepare_v2 error");
sqlite3_close(pdb);
return -1;
}
while (1)
{
int id;
char name[256]={0};
float score;
scanf("%d%s%f",&id,name,&score);
getchar();
//绑定参数/变量
int index[3];
index[0]=sqlite3_bind_parameter_index(pstmt,"@id");
index[1]=sqlite3_bind_parameter_index(pstmt,"@name");
index[2]=sqlite3_bind_parameter_index(pstmt,"@score");
sqlite3_bind_int(pstmt,index[0],id);
sqlite3_bind_text(pstmt,index[1],name,strlen(name),NULL);
sqlite3_bind_int(pstmt,index[2],score);
ret=sqlite3_step(pstmt);
if(ret!=SQLITE_DONE)
{
perror("sqlite3_step error\n");
return -1;
}
sqlite3_reset(pstmt);
}
sqlite3_finalize(pstmt);
sqlite3_close(pdb);
}
一步查询执行操作函数 sqlite3_exec
sqlite3_exec内部封装了三个函数[sqlite3_prepare_v2 sqlite3_step sqlite3_finalize]
他是一个万能函数 它可以让应用程序执行多个SQL语句 而不需要使用sqlite3中其他的大量的接口函数
SQLITE_API 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 */
);
函数功能: 指定一条指定的sql语句
参数列表:
第一个参数: 一个打开的数据库连接对象
第二个参数: 是你要准备执行的sql语句
第三个参数: 回调函数: 当执行sqlite3_exec后 有可能会执行此回调函数
填NULL 就表示你不需要执行回调函数
什么时候需要回调函数? 当你做SELECT时 就需要回调函数。
那么SELECT时候的回调函数是干嘛? 就是把你select查询的结果输出出来
select产生多少条结果 回调函数就会执行多少次。
第四个参数: 你需要传递到回调函数中的信息 类似于pthread-create中给线程函数传参
如果你不需要传递任何消息 就填NULL 如果多个消息 请自行封装成结构体
第五个参数: 二级指针 保存一级指针的地址 保存执行的出错的信息
一旦出错 则将错误信息写入[sqlite3_malloc]分配的空间中 并且让第5个参数保存分配的空间的地址
为了避免内存泄露 应用程序在处理完错误信息之后 需要调用sqlite3_free释放掉第五个参数指向的内容空间
使用sqlite3_exec函数实现数据库查询功能
//编译的时候需要加上 -lsqlite3
#include <stdio.h>
#include <string.h>
#include <sqlite3.h>
int flag=0;
int callback(void *arg,int ncols,char *col_value[],char*col_name[])
{
int i;
if(flag==0)
{
for(i=0;i<ncols;i++)
{
printf("%s\t\t",col_name[i]);
}
flag=1;
}
printf("\n");
for(i=0;i<ncols;i++)
{
printf("%s\t\t",col_value[i]);
}
putchar('\n');
return 0;
}
int main(int argc,char * argv[])
{
//创建一个连接对象
sqlite3 * pbd;
//打开连接对象
int ret=sqlite3_open(argv[1],&pbd);
if(ret!=SQLITE_OK)
{
perror("sqlite3_open error\n");
return -1;
}
const char * sql="select * from student;";
char * errmsg=NULL;
ret=sqlite3_exec(pbd,sql,callback,NULL,&errmsg);
if(ret!=SQLITE_OK)
{
printf("error:%s\n",errmsg);
return -1;
}
//关闭连接
sqlite3_close(pbd);
return 0;
}
回调函数详解:
int (*callback)(void* arg,int x,char** a,char** b)
第一个参数: 是一个指针 可以传入用户自己的数据
第二个参数: 是执行select语句后 查询到的结果的列数
第三个参数: 是一个指向字符串的指针数据 就是结果数据每一列的信息
第四个参数: 是一个指向字符串的指针数据 就是结果数据每一列的表头的信息
select产生多少条结果 回调函数就会被调用多少次
更多推荐
已为社区贡献3条内容
所有评论(0)