当前位置: 首页 > news >正文

婚庆网站制作西安做网站陕西必达

婚庆网站制作,西安做网站陕西必达,青岛网站建设设计,红酒公司网站源码目录 sqlite3的C/C API应用 前言 SQLite3库安装 API函数 打开、关闭、错误处理 打开 返回值 关闭 错误调试 实际应用 执行SQL#xff08;DDL、DML#xff09; API介绍 实际应用 回调函数查询 API介绍 实际应用 全缓冲查询 API介绍 实际应用 字节缓冲查询…目录 sqlite3的C/C API应用 前言 SQLite3库安装 API函数 打开、关闭、错误处理 打开 返回值 关闭 错误调试 实际应用 执行SQLDDL、DML API介绍 实际应用 回调函数查询 API介绍 实际应用 全缓冲查询 API介绍 实际应用 字节缓冲查询 API介绍 实际应用 三种查询方式总结 sqlite实现C语言自定义函数封装 sqlite3的C/C API应用 前言 对于主键和外键知识点的补充 主键的值不能重复一般将自增的字段设置为主键。 主键是用来唯一表示一条数据的值不能重复的。比如一条记录包括身份正号姓名年龄。身份证号是唯一能确定你这个人的其他都可能有重复所以身份证号薯磨是主键。外键主要目的是控制存储在外键表中的数据。 使两张表形成关联外键只能引用外表中的列的值或使用空值。 外键用于与另一张表的关联。是能确定另一张表记录的字段用于保持数据的一致性。比如A表中的一个字段是B表的主键那他就可以是A表的外键。 SQLite3库安装 在 C/C 程序中使用 SQLite 之前我们需要确保机器上已经有 SQLite 库这个库提供了C/C的操作SQLite的编程接口API。 在linux下只需输入安装命令sudo apt-get install libsqlite3-devQT下使用SQLite3数据库 https://www.cnblogs.com/tfanalysis/p/4073756.html Windows下https://www.cnblogs.com/White-strategy-group/p/6360003.html 我使用的是Windows下通过vscode远程SSH访问Linux因此需要在windows下也安装并添加相应的库文件。 安装前我们在vscode中添加SQLite的头文件提示找不到头文件 因此我们需要先定位头文件包含路径 然后到sqlite官网下载源码包sqlite3的源码 https://www.cnblogs.com/White-strategy-group/p/6360003.html 解压缩后文件内容如图所示 将三个.h文件添加到之前的includePath中D:/myinclude/** 我们先在目录下新建一个sqlite文件夹 然后将头文件添加进来 如果发现添加完之后仍然自动找不到头文件如下所示 我们需要手动包含具体头文件路径如D:\\myinclude\\sqlite3 我们输入sqlite3发现可以自动提示补全则表示库文件添加成功 API函数 打开、关闭、错误处理 打开 第一个参数为指定要打开的数据库的名字也包括数据库的路径 第二个参数为一个二级指针这里的作用相当于文件描述符它是一个数据库文件指针。传入的是一个一级指针的地址作为输出给指针的具体指向赋值定义一个空指针传入过来最终会给这个指针赋值通过操作数据库文件指针就相对于操作数据库 返回值 SQLite3的C/C接口函数所有返回值如下: #define SQLITE_OK 0 /* Successful result */ #define SQLITE_ERROR 1 /* SQL error or missing database */ #define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */ #define SQLITE_PERM 3 /* Access permission denied */ #define SQLITE_ABORT 4 /* Callback routine requested an abort */ #define SQLITE_BUSY 5 /* The database file is locked */ #define SQLITE_LOCKED 6 /* A table in the database is locked */ #define SQLITE_NOMEM 7 /* A malloc() failed */ #define SQLITE_READONLY 8 /* Attempt to write a readonly database */ #define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */ #define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ #define SQLITE_CORRUPT 11 /* The database disk image is malformed */ #define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */ #define SQLITE_FULL 13 /* Insertion failed because database is full */ #define SQLITE_CANTOPEN 14 /* Unable to open the database file */ #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ #define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* Too much data for one row of a table */ #define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */ #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ #define SQLITE_ROW 100 /* sqlite_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite_step() has finished executing */关闭 错误调试 返回错误信息 返回值错误码 实际应用 #include stdio.h #include sqlite3.hint main(int argc, char const *argv[]) {sqlite3 *db;int ret sqlite3_open(argv[1],db);if(ret ! SQLITE_OK){printf(sqlite3 open:%s\n,sqlite3_errmsg(db));exit(-1);}printf(sqlite open db successfully!\n);sqlite3_close(db);return 0; }编译的时候不能直接编译 我们需要像使用POSIX库一样手动链接sqlite3库 运行结果 但是该函数有个bug即使不传任何参数也不会报错 因此最好添加一个命令行传参判断 #include stdio.h #include sqlite3.hint main(int argc, char const *argv[]) {if(argc ! 2){printf(Please input db name!\n);exit(-1);}sqlite3 *db;int ret sqlite3_open(argv[1],db);if(ret ! SQLITE_OK){printf(sqlite3 open:%s\n,sqlite3_errmsg(db));exit(-1);}printf(sqlite open db successfully!\n);sqlite3_close(db);return 0; }执行SQLDDL、DML API介绍 执行SQL语句函数该函数一共有5个参数 参数1数据库文件句柄 参数2要执行的SQL语句 参数3回调函数传入一个函数指针这里的sqlite_callback callback中的sqlite_callback是通过函数指针重命名的如下图所示。注回调函数只对SQL查询语句有效。当指定的是一个非查询操作该参数应该置为NULL否则即使传入了回调函数回调函数也不会被执行。 参数4回调函数的参数 参数5保存执行SQL后的错误信息传入的是一级指针的地址 实际应用 我们首先创建一个学生表其中我们对错误检查进行了二次封装 #include stdio.h #include sqlite3.h #include string.h #include stdlib.hvoid print_error(int ret, char *err, sqlite3 *db) {if(ret ! SQLITE_OK){printf(%s:%s\n,err,sqlite3_errmsg(db));exit(-1);} }int main(int argc, char const *argv[]) {if(argc ! 2){printf(Please input db name!\n);exit(-1);}sqlite3 *db;char *errmsg;char sql[1024] {0};int ret sqlite3_open(argv[1],db);print_error(ret,sqlite open,db);printf(sqlite open db successfully!\n);strcpy(sql,create table student(id integer primary key, name text, age integer));ret sqlite3_exec(db,sql,NULL,NULL,errmsg);print_error(ret,sqlite exec create table,db);printf(create table successfully\n);sqlite3_close(db);return 0; }然后通过键盘输入的方式往表里插入三条数据 #include stdio.h #include sqlite3.h #include string.h #include stdlib.hvoid print_error(int ret, char *err, sqlite3 *db) {if(ret ! SQLITE_OK){printf(%s:%s\n,err,sqlite3_errmsg(db));exit(-1);} }int main(int argc, char const *argv[]) {if(argc ! 2){printf(Please input db name!\n);exit(-1);}sqlite3 *db;char *errmsg;char sql[1024] {0};int id;char name[20];int age;int ret sqlite3_open(argv[1],db);print_error(ret,sqlite open,db);printf(sqlite open db successfully!\n);strcpy(sql,create table if not exists student(id integer primary key, name text, age integer));ret sqlite3_exec(db,sql,NULL,NULL,errmsg);print_error(ret,sqlite exec create table,db);printf(create table successfully\n);//插入3行数据id,name,age 键盘输入for(int i0;i3;i){printf(Please input id:\n);scanf(%d,id);printf(Please input name:\n);scanf(%s,name);printf(Please input age:\n);scanf(%d,age);//sql:insert into student(id,name,age)values();//sprint();写入到字符串 fprintf();写入到文件memset(sql,0,sizeof(sql));sprintf(sql,insert into student(id,name,age)values(%d,%s,%d),id,name,age);ret sqlite3_exec(db,sql,NULL,NULL,errmsg);print_error(ret,sqlite exec create table,db);}sqlite3_close(db);return 0; }如果我们想要删除zhangsan的数据可以使用如下 #include stdio.h #include sqlite3.h #include string.h #include stdlib.h #define DELETE_DATA 1 #define INSERT_DATA 0 void print_error(int ret, char *err, sqlite3 *db) {if(ret ! SQLITE_OK){printf(%s:%s\n,err,sqlite3_errmsg(db));exit(-1);} }int main(int argc, char const *argv[]) {if(argc ! 2){printf(Please input db name!\n);exit(-1);}sqlite3 *db;char *errmsg;char sql[1024] {0};int id;char name[20];int age;int ret sqlite3_open(argv[1],db);print_error(ret,sqlite open,db);printf(sqlite open db successfully!\n);strcpy(sql,create table if not exists student(id integer primary key, name text, age integer));ret sqlite3_exec(db,sql,NULL,NULL,errmsg);print_error(ret,sqlite exec create table,db);printf(create table successfully\n);#if INSERT_DATA//插入3行数据id,name,age 键盘输入for(int i0;i3;i){printf(Please input id:\n);scanf(%d,id);printf(Please input name:\n);scanf(%s,name);printf(Please input age:\n);scanf(%d,age);//sql:insert into student(id,name,age)values();//sprint();写入到字符串 fprintf();写入到文件memset(sql,0,sizeof(sql));sprintf(sql,insert into student(id,name,age)values(%d,%s,%d),id,name,age);ret sqlite3_exec(db,sql,NULL,NULL,errmsg);print_error(ret,sqlite exec create table,db);} #endif#if DELETE_DATAprintf(Please input who do you want to delete:\n);memset(sql,0,sizeof(sql));memset(name,0,sizeof(name));scanf(%s,name);sprintf(sql,delete from student where name %s,name);ret sqlite3_exec(db,sql,NULL,NULL,errmsg);print_error(ret,sqlite exec delete data,db); #endifsqlite3_close(db);return 0; }注SQLite库提供的是原生态的接口我们可以对其进行二次封装像之前错误检查那样对sqlite3_exec要执行的SQL语句进行封装避免代码的冗余。 回调函数查询 API介绍 每查询到一条结果就会回调一次这个函数通过一行行缓冲数据每次缓冲一行。 参数1传入的参数 参数2保存查询到的结果每一行中列的个数 参数3保存查询到数据中每一列的值用一个指针数组保存指针的数组本质是数组来接 参数4保存每一列的字段名字用一个指针数组来接 实际应用 以打印查询到的结果每行列数为例如果回调函数不加return 0;那么将只执行一次 将上return 0;才可以执行全部 如果想要打印查询到的每一列结果 再加上每一列相应的字段名 注意对于外部传入回调函数的参数是无法修改的具体原因可能是由于内部机制 如我们传入一个flag变量然后出函数打印结果 我们在回调函数内对flag进行 但出函数之后值仍是0 如果查询不到结果将会什么信息也不会输出 我们可以通过定义一个全局变量标志位进行判断是否查询到数据 #include stdio.h #include sqlite3.h #include stdlib.h #include string.hint flag0;void print_error(int ret, char *err, sqlite3 *db) {if(ret ! SQLITE_OK){printf(%s:%s\n,err,sqlite3_errmsg(db));exit(-1);}printf(%s:successfully!\n,err); }int my_sqlite_callback(void *para,int columnCount,char **columnValue,char**columnName) {printf(columnCount %d\n, columnCount);flag1;for(int i 0; i columnCount;i){printf(%s:%s|,columnName[i],columnValue[i]);}printf(\n);return 0; }int main(int argc, char const *argv[]) {if(argc ! 2){printf(Please input db name!\n);exit(-1);}sqlite3 *db;char *errmsg;char sql[1024] {0};int ret sqlite3_open(argv[1],db);print_error(ret,sqlite open,db);printf(sqlite open db successfully!\n);strcpy(sql,select * from student where name zhangsan);sqlite3_exec(db,sql,my_sqlite_callback,NULL,errmsg);print_error(ret,select,db);if(flag0){printf(The data queried is empty!\n);}sqlite3_close(db);return 0; }全缓冲查询 API介绍 与sqlite_exec不同sqlite3_get_table是专门用于查询数据的通过一次性将所有查询到的数据缓冲起来 参数1数据库文件句柄 参数2数据库SQL语句 参数3三维指针用于保存查询到的结果 参数4查询到的结果总共的行数 参数5查询到的结果总共的列数 参数6保存查询出错的信息 以三维指针为例我们可以创建一个变相的二维数组 可以想象创建一个长方体 char ***result; result (char***)malloc(sizeof(char**)*4);创建四个存储空间 *result (char**)malloc(sizeof(char*)*4);每个存储空间里再创建四个存储空间 **result (char*)malloc(sizeof(char)*4);每个存储空间里再创建一个字符串数组 最终在逻辑上形成16个连续的存储空间物理上不连续 我们可以通过三次for循环来创建 但访问方式仍是一维数组的访问方式因为通过指针创建的空间本质还是链式的不是真正的多维数组 实际应用 实际使用时我们需要定义一个二维指针将它的地址作为参数传入查询到的数据都将保存在二维指针中 发现打印是从字段开始打印的最后少了一行数据这是因为保存的数据包括了字段那一行但是返回的行数nrow只算了实际数据的行数 因此需要改正如下 这样输出的结果就是正确的了 最后一定要记得调用释放空间函数sqlite3_free_table因为库函数sqlite3_get_table的内部分配了堆区空间 全缓冲查询程序如下 #include stdio.h #include sqlite3.h #include stdlib.h #include string.hvoid print_error(int ret, char *err, sqlite3 *db) {if(ret ! SQLITE_OK){printf(%s:%s\n,err,sqlite3_errmsg(db));exit(-1);}printf(%s:successfully!\n,err); }int main(int argc, char const *argv[]) {if(argc ! 2){printf(Please input db name!\n);exit(-1);}sqlite3 *db;char *errmsg;char sql[1024] {0};int ret sqlite3_open(argv[1],db);print_error(ret,sqlite open,db);printf(sqlite open db successfully!\n);char **result;int nrow;int ncolumn;strcpy(sql,select * from student);ret sqlite3_get_table(db,sql,result,nrow,ncolumn,errmsg);print_error(ret,select,db);for(int i 1; inrow; i){for(int j 0; j ncolumn; j){printf(%s|,result[i*ncolumnj]);}printf(\n);}sqlite3_free_table(result);sqlite3_close(db);return 0; }字节缓冲查询 API介绍 sqlite3_prepare 作用把SQL语句转成字节码由后面的执行函数去执行将查询到的数据做字节缓冲 参数1数据库文件句柄 参数2SQL语句 参数3SQL语句的最大字节数一般设为-1 参数4Statement句柄即字节序句柄 参数5SQL语句无用部分的指针一般设为NULL 字节缓冲查询还涉及到了以下函数 sqlite3_step从第一行开始查询每次查询一行每调用一次该函数会继续查询下一行数据数据不为空则返回SQLITE_ROW sqlite3_column_count获取结果的列数 sqlite3_column_text获取程序的结果当前行中每一列的数据 sqlite3_finalize用于销毁字节序句柄 实际应用 #include stdio.h #include sqlite3.h #include stdlib.h #include string.hvoid print_error(int ret, char *err, sqlite3 *db) {if(ret ! SQLITE_OK){printf(%s:%s\n,err,sqlite3_errmsg(db));exit(-1);}printf(%s:successfully!\n,err); }int main(int argc, char const *argv[]) {if(argc ! 2){printf(Please input db name!\n);exit(-1);}sqlite3 *db;char *errmsg;char sql[1024] {0};int ret sqlite3_open(argv[1],db);print_error(ret,sqlite open,db);printf(sqlite open db successfully!\n);int rc,i,j;int ncolumn;sqlite3_stmt *stmt;strcpy(sql,select * from student);rc sqlite3_prepare(db,sql,-1,stmt,NULL);if(rc){printf(query fail!\n);}else{printf(query success!\n);rc sqlite3_step(stmt);//查询成功则返回值rcSQLITE_ROWncolumn sqlite3_column_count(stmt);//获取列数while(rc SQLITE_ROW){for(i 0;incolumn;i){printf(%s|,sqlite3_column_text(stmt,i));//获取每一列的数据}printf(\n);rc sqlite3_step(stmt);//继续获取下一行数据}}sqlite3_finalize(stmt);sqlite3_close(db);return 0; }三种查询方式总结 回调函数查询内存开销小但查询效率相对较低全缓冲查询的查询效率高但是内存消耗大字节缓冲查询兼具查询效率和低开销。优先使用第三种查询方法 sqlite实现C语言自定义函数封装 由于数据库提供的API接口过于复杂使用的过程顺序也很繁琐所以对于原生态的API在实际工作开发中会进行一层封装减少调用传参减少调用次数增加代码可读性提高开发效率。 可封装如下包括创建数据库、建表、插入数据、查询数据、删除数据 database.h #ifndef _DATABASE_H_ #define _DATABASE_H_#include stdio.h #include string.h #include unistd.h #include stdlib.h #include errno.h #include libgen.h #include sqlite3.hextern int open_database(sqlite3 **db,char *database_name); extern int create_table(sqlite3 **db,char *table_name,char *table_attribute); extern int insert_data(sqlite3 **db,char *table_name,char *attr,char *msg); extern int query_data(sqlite3 **db,char ***azResult,char *table_name); extern int delete_data(sqlite3 **db,char *table_name);#endif database.c #include database.hchar sql[128]; char *zErrMsgNULL; int nrow0; int ncolumn 0;int open_database(sqlite3 **db,char *database_name) {int len;len sqlite3_open(database_name,db);if(len){printf(Open database name %s failure.\n,database_name);sqlite3_close(*db);return -1;}printf(Open a sqlite3 database name %s successfully!\n,database_name);return 0; }int create_table(sqlite3 **db,char *table_name,char *table_attribute) {snprintf(sql,sizeof(sql),CREATE TABLE %s(%s);,table_name,table_attribute);//log_info(sql%s\n,sql);//sqlCREATE TABLE test(TEST CHAR(100));;if(sqlite3_exec(*db,sql,NULL,NULL,zErrMsg)!SQLITE_OK){printf(Table %s already exist\n,table_name);}else{printf(Create table %s successfully\n,table_name);}}int insert_data(sqlite3 **db,char *table_name,char *attr,char *msg) {snprintf(sql,sizeof(sql),INSERT INTO %s(%s) VALUES(%s);,table_name,attr,msg); //插入数据if(sqlite3_exec(*db,sql,NULL,NULL,zErrMsg)!SQLITE_OK){sqlite3_close(*db);printf(Insert %s to table %s failure:%s\n,msg,table_name,strerror(errno));return -1;}printf(Insert %s to table %s successfully\n,msg,table_name);return 0; }int query_data(sqlite3 **db,char ***azResult,char *table_name) {snprintf(sql,sizeof(sql),select *from %s;,table_name);//sqlselect *from test;if(sqlite3_get_table(*db,sql,azResult,nrow,ncolumn,zErrMsg)!SQLITE_OK){sqlite3_close(*db);printf(Select *from %s failure\n,table_name);return -1;}printf(There are %d pieces of data in table %s\n,nrow,table_name);return nrow; }int delete_data(sqlite3 **db,char *table_name) {snprintf(sql,sizeof(sql),delete from %s;,table_name);//sqldelete from test;if(sqlite3_exec(*db,sql,NULL,NULL,zErrMsg)!SQLITE_OK){sqlite3_close(*db);printf(Delete from %s failure\n,table_name);return -1;}printf(Delete data from table %s successfully!\n,table_name);return 0; } test_database.c #include database.hint main(void) {sqlite3 *db;char **azResultNULL;if( open_database(db,test.db)0 )return -1;if( create_table(db,test,TEST CHAR(100))0 )return -2;if( insert_data(db,test,TEST,Test nihao)0 )return -3;if( query_data(db,azResult,test)0 )return -4;if( delete_data(db,test)0 )return -5;if( query_data(db,azResult,test)0 )return -6;return 0; }
http://www.tj-hxxt.cn/news/226302.html

相关文章:

  • wordpress 网站地图插件wordpress图片尺寸 样式
  • 建筑网站推荐艺术网站建设
  • 建设部相关网站利用html做博客网站
  • 网站负责人 备案网站空间的权限
  • 商务网站建设sz886网站引流推广
  • 成都六度网站建设网站制作全包多少钱
  • 模板网站哪个平台好有经验的扬中网站建设
  • 绿色风格的网站南京建设网站多少钱
  • 网站怎么做可以合法让别人充钱微商城开店
  • 网站模板更换厦门网站建设设
  • 企业网站备案要求厦门建设局咨询电话
  • 电子简历模板抖音seo排名优化公司
  • 深圳麒麟网站建设青岛网站建设代理加盟
  • 网站推广的目的是什么网页素材及网站架构制作
  • 怀化租房网站关键词优化公司费用多少
  • 企业网站完整版vi设计百科
  • 江苏省教育网站官网找别人建网站去哪里
  • 建一个网站要多久如何充实网站内容
  • 网站开发页面适应高度商家商城小程序
  • 织梦网站栏目建设商丘微网站
  • 郴州网站seo微信公众号怎么创建文章
  • 外贸建设网站中力建设网站
  • 专业的深圳网站设计免费的网站免安装
  • 经常做ppt的网站wordpress后台登录网址
  • 房地产网站建设招商wordpress 有道智云
  • 站长工具seowordpress导入用户数据库
  • 百度公司网站推广怎么做计算机基础培训机构
  • 重庆网站建设招聘如何在百度免费发布广告
  • 水果网站首页设计wordpress付费主题破解版
  • 建设银行投诉网站dw如何发布网页