我们可以直接访问数据库,当然我们也需要在程序中连接数据库。
接下来我将介绍嵌入式MySQL服务器库。
使用嵌入式 MySQL 服务器库, 能够在客户端应用程序中使用具备全部特性的 MySQL 服务器。 主要优点在于,增加了速度,并使得嵌入式应用程序的管理更简单。嵌入式服务器库是以 MySQL 的客户端/ 服务器版本为基础的, 采用 C/C++语言编写。 其结果是嵌入式服务器也是用 C/C++语言编写的。 在其他语言中, 嵌入式服务器不可用。
具体简单步骤:

1.获取或者初始化MYSQL结构

首先MYSQL是一个结构类型,该结构代表 1 个数据库连接的句柄。 几乎所有的 MySQL 函数均使用它。
函数介绍

MYSQL *mysql_init(MYSQL *mysql)
/*分配或初始化与 mysql_real_connect()相适应的 MYSQL 对象。 如果 mysql 是 NULL 指针,该函数将分配、 初始化、 并返回新对象。 否则, 将初始化对象, 并返回对象的地址。 如果mysql_init()分配了新的对象, 当调用 mysql_close()来关闭连接时。 将释放该对象。初始化的 MYSQL*句柄。 如果无足够内存以分配新的对象, 返回 NULL。
*/

我们来获得一个句柄

MYSQL *mysql =mysql_init(NULL); //获得数据库连接的句柄,分配或初始化与 mysql_real_connect()相适应的 MYSQL 对象
if(mysql == null){printf("mysql_init error!\n");return -1;
}

2.尝试与数据库引擎建立连接

我们会用到一个函数
函数介绍

MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const
char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag)
/*
描述:mysql_real_connect()尝试与运行在主机上的 MySQL 数据库引擎建立连接。 在你能够执行
需要有效 MySQL 连接句柄结构的任何其他 API 函数之前, mysql_real_connect()必须成功完成。
第 1 个参数应是已有 MYSQL 结构的地址。 调用 mysql_real_connect()之前, 必须调
用 mysql_init()来初始化 MYSQL 结构。
“host”的值必须是主机名或 IP 地址。 如果“host”是 NULL 或字符串"localhost", 连接
将被视为与本地主机的连接。
“user”参数包含用户的 MySQL 登录 ID。 如果“user”是 NULL 或空字符串"", 用户将
被视为当前用户。
“passwd”参数包含用户的密码。 如果“passwd”是 NULL, 仅会对该用户的(拥有 1
个空密码字段的) 用户表中的条目进行匹配检查。
“db”是数据库名称。 如果 db 为 NULL, 连接会将默认的数据库设为该值。
如果“port”不是 0, 其值将用作 TCP/IP 连接的端口号。
如果 unix_socket 不是 NULL, 该字符串描述了应使用的套接字或命名管道。
client_flag 的值通常为 0,
*/

我们来尝试连接

mysql = mysql_real_connect(mysql,"localhost(主机)","root(用户)","password(密码)","databases(数据库名称)",3306,NULL,0);
if(mysql == NULL){printf("mysql_real_connect error:%s\n",mysql_error(mysql));//mysql_error()这个函数返回上次调用的MYSQL函数的错误信息,是一串以null终结的字符串return -1;
}

3.执行SQL语句

连接上数据库后,我们就可以执行SQL语句了,这些语句可以是DDL,DQL,DML等等语句,由用户自己输入。
函数介绍

 mysql_query(MYSQL *mysql,const char *sql);/*执行由“Null 终结的字符串”查询指向的 SQL 查询。 正常情况下, 字符串必须包含 1 条 SQL
语句, 而且不应为语句添加终结分号(‘;’) 或“\g”。 如果允许多语句执行, 字符串可包含多条由分号隔开的语句。如果希望了解查询是否应返回结果集, 可使用 mysql_field_count()进行检查如果查询成功, 返回 0。 如果出现错误, 返回非 0 值。*/

接下来我们自己输入想要执行的SQL语句

char query[1024]={};
printf("mysql>");
gets(query);
if(strcmp(query,"quit") == 0 || strcmp(query,"exit") == 0){//当输入的sql语句是quit或者exit时,退出该嵌入式服务器printf("Bye!\n");break;
}
mysql_query(mysql,"set names utf8");
//这行代码的作用是当设置环境为utf-8编码,
//如果不设置,很有可能中文字符无法正常显示,会显示为一堆乱码
int ret = mysql_query(mysql,query);
//执行sql语句
if(ret != 0){printf("mysql_query error:%s\n",mysql_error(mysql));continue;
}

4.获得结果集

当我们执行完一条sql语句后,可能有结果集,也有可能没有结果集,所以接下来我们将会用个函数来接收一个结果集。
函数介绍

MYSQL_RES * mysql_store_result(MYSQL *mysql);
/*
对于成功检索了数据的每个查询(SELECT、 SHOW、 DESCRIBE、 EXPLAIN、 CHECKTABLE 等) ,
必须调用 mysql_store_result()或 mysql_use_result()
于其他查询, 不需要调用 mysql_store_result()或 mysql_use_result(), 但是如果在任何情
况下均调用了 mysql_store_result(), 它也不会导致任何伤害或性能降低。 通过检查
mysql_store_result()是否返回 0,
如果查询未返回结果集, mysql_store_result()将返回 Null 指针(例如, 如果查询是 INSERT
语句) 。
如果读取结果集失败, mysql_store_result()还会返回 Null 指针。 通过检查 mysql_error()是
否返回非空字符串, mysql_errno()是否返回非 0 值, 或 mysql_field_count()是否返回 0, 可
以检查是否出现了错误。
如果未返回行, 将返回空的结果集。 (空结果集设置不同于作为返回值的空指针) 。
*/

那我们看一下执行完sql语句后的结果集如何
我们还需要介绍一下另外一个结构体MYSQL_RES,该结构代表返回行的查询结果(SELECT, SHOW, DESCRIBE, EXPLAIN) 。

MYSQL *result = mysql_store_result(mysql);
if(result == NULL){if(mysql_errno(mysql) != 0){printf("mysql_store_result error:%s\n",mysql_error(mysql));return -1;   }else{printf("Query OK!\n");continue;}/*有必要解释这几行代码,当result为空的时候,会有两种情况,第一种就是出现了错误,
//那我们需要显示错误信息,当发生错误时,mysql_errno()会返回上次调用的 MySQL 函数的错误编号,
//这个编码为非0值,所以当mysql_errno(mysql) != 0时就是表示发生了错误。所以当mysql_errno(mysql) == 0时表示没有出现错误,但是没有结果集,
//比如当我们执行DML,DDL,TCL语句时就不会反回结果,这回返回影响了几条记录,比如"Query OK, 1 row affected (0.00 sec)"*/
}

5.显示结果集

当我们获得结果集后,就需要显示结果集了,首先我们需要知道这个结果集中一行(即一条记录,元组)的信息,这时候我们又有了另外两个结构体类型 MYSQL_ROWh和MYSQL_FIELD。
MYSQL_ROW这是 1 行数据的“类型安全”表示。 它目前是按照计数字节字符串的数组实施的。 (如果字段值可能包含二进制数据, 不能将其当作由 Null 终结的字符串对待, 这是因为这类值可能会包含 Null 字节) 。 行是通过调用 mysql_fetch_row()获得的。
MYSQL_FIELD该结构包含关于字段的信息, 如字段名、 类型和大小。 这里详细介绍了其成员。 通过重复调用 mysql_fetch_field(), 可为每个字段获得 MYSQL_FIELD 结构。 字段值不是该结构的组成部份, 它们包含在 MYSQL_ROW 结构中。

接下来我们看一下该如何显示结果集
函数介绍

unsigned int mysql_num_fields(MYSQL_RES *result);
//返回结果集中的行数。注意, 你可以从指向结果集的指针或指向连接句柄的指针获得行数。
MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result);
//对于结果集, 返回所有 MYSQL_FIELD 结构的数组。 每个结构提供了结果集中 1 列的字段定义。
my_ulonglong mysql_num_rows(MYSQL_RES *result);
//返回结果集中的行数。
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
//检索结果集的下一行。 在 mysql_store_result()之后使用时, 如果没有要检索的行,
//mysql_fetch_row()返回 NULL。 在 mysql_use_result()之后使用时, 如果没有要检索的行或出现了
//错误, mysql_fetch_row()返回 NULL。

具体代码实现

unsigned int fields = mysql_num_fields(result);
MYSQL_ROW record;
MYSQL_FIELD *fl = mysql_fetch_field(result);
size_t i;
printf("**************************\n");
for(i=0;i<fields;i++){printf("%-15s ",fl[i].name);
}
printf("\n");
while(record = mysql_fetch_row(result)){for(i=0;i<fileds;i++){printf("%-10s  ",record[i]);}printf("\n");
}
my_ulonglong rows = mysql_num_rows(result);
printf("%lu rows in set (0.012 sec)\n",(unsigned long int)(rows));

6.释放资源,关闭连接

当我们完成数据库的操作后,需要释放资源和关闭连接,否则会出现其他许多问题。
函数介绍

void mysql_free_result(MYSQL_RES *result);
//释放由 mysql_store_result()、 mysql_use_result()、 mysql_list_dbs()等为结果集分配的内存。
//完成对结果集的操作后, 必须调用 mysql_free_result()释放结果集使用的内存
void mysql_close(MYSQL *mysql);
//关闭前面打开的连接。 如果句柄是由 mysql_init()或 mysql_connect()自动分配的,
//mysql_close()还将解除分配由 mysql 指向的连接句柄。

最后我们关闭连接,释放资源

if(result != NULL){
//如果当我们执行的第一句sql语句就是exit或者quit时,此时result仍未null,
//那这时候不需要释放,如果强行释放就会产生段错误.mysql_free_result(result);
}
mysql_close(mysql);

7.全部源代码

最后我们以这份源代码收尾

#include <mysql/mysql.h>
#include <stdio.h>int main(){MYSQL *mysql = mysql_init(NULL);if(mysql == NULL){printf("mysql_init error!\n");return -1;}mysql = mysql_real_connect(mysql,"localhost","root","123456","test",3306,NULL,0);//这里需要根据每个数据库的具体数据来写参数if(mysql == NULL){printf("mysql_real_connect error:%s\n",mysql_error(mysql));return -1;}MYSQL_RES *result=NULL;while(1){char query[1024] = {};printf("mysql>");gets(query);if(strcmp(query,"quit") == 0 || strcmp(query,"exit") == 0){printf("Bye\n");break;}mysql_query(mysql,"set names utf8");int ret = mysql_query(mysql,query);if(ret != 0){printf("mysql_query error:%s\n",mysql_error(mysql));continue;}result = mysql_store_result(mysql);   //获得结果集if(result == NULL){if(mysql_errno(mysql) != (unsigned int)(0)){printf("mysql_store_result error:%s\n",mysql_error(mysql));return -1;}else{continue; }}unsigned int fields = mysql_num_fields(result);MYSQL_ROW record;MYSQL_FIELD *fl = mysql_fetch_field(result);size_t i;printf("**************************\n");for(i=0;i<fields;i++){printf("%-15s ",fl[i].name);    }printf("\n");while(record = mysql_fetch_row(result)){for(i=0;i<fields;i++){printf("%-10s     ",record[i]);  }printf("\n");}my_ulonglong rows = mysql_num_rows(result);printf("%lu rows in set (0.012 sec)\n",(unsigned long int)(rows));}if(result!=NULL){mysql_free_result(result);}mysql_close(mysql);return 0;
}

在运行这段程序前,我们还需要下载一个库libmysqlclient或者,平台不同要下载的东西也不同,但是大致都一样。

8.运行效果

最后的最后我们来看一下结果怎么样?

BYEBYE;

C语言实现程序连接数据库并实现简单的嵌入式服务器相关推荐

  1. c 对一个mysql数据库进行操作_用C语言操作MySQL数据库

    函数 描述 mysql_affected_rows() 返回上次UPDATE.DELETE或INSERT查询更改/删除/插入的行数. mysql_autocommit() 切换autocommit模式 ...

  2. 如何用c 控制mysql数据库_用C语言操作MySQL数据库

    函数 描述 mysql_affected_rows() 返回上次UPDATE.DELETE或INSERT查询更改/删除/插入的行数. mysql_autocommit() 切换autocommit模式 ...

  3. 用C语言操作MySQL数据库

    http://blog.chinaunix.net/uid-26743670-id-3479887.html 参考MYSQL的帮助文档整理 这里归纳了C API可使用的函数,并在下一节详细介绍了它们. ...

  4. ocbase 数据库 蚂蚁_iOS开发数据库篇—FMDB简单介绍

    iOS开发数据库篇-FMDB简单介绍 一.简单说明 1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来 ...

  5. java mysql nclob_java语言操作Oracle数据库中的CLOB数据类型 (转)

    java语言操作Oracle数据库中的CLOB数据类型 (转)[@more@] 有关字段类型的相关信息可以查阅oracle技术网.下面摘抄一些有关blob.clob等类型的说明.又便于大家的了解. 字 ...

  6. mysql多语言运营设计_多语言系统的数据库设计

    之前做的项目涉及到中国大陆和纽伦新港的用户使用,也就需要做成一个多语言的系统,现在总结下其中一些经验和思考. 首先我们需要确认我们要做的系统,多语言到底是要做多少种语言,以后会不会要求增加更多的语言. ...

  7. c语言访问mysql,C语言访问mysql数据库

    mysql中新建的数据库为hyx,hyx中的表为my_schema,表中的数据为下图: 编写代码,访问表中的数据,测试代码如下: #include "stdafx.h" #incl ...

  8. c语言sqlserver数据库头文件,Mysql的C语言API进行数据库编程

    数据编程基础知识,掌握C语言,熟悉简单的SQL语句,能够实现简单的增.删.查.改即INSERT.DELETE .SELECT.UPDATE语句,其中SELECT语句尤为重要,面试笔试中经常被问及.默认 ...

  9. c语言操作redis数据库

    前言 redis(Remote Dictionary Server)是一个使用ANSI C编写的开源.支持网络.基于内存.可选持久性的键值对存储数据库–来自维基百科.由于其读写性能高.数据结构丰富.支 ...

最新文章

  1. 滴滴行程单用的什么字体_打车就送冰淇淋!滴滴出行放大招,限时19天
  2. Leetcode--145. 二叉树的后序遍历(迭代递归)
  3. 前端网页广告无线翻滚_从小白到web前端工程师进阶之路 从0到1到更深
  4. 通过ntdll.dll提供的API函数实现当前进程的枚举
  5. Google AdSense实战宝典
  6. 用mysql创建图书信息表_数据库创建图书管理系统
  7. Quartz定时任务
  8. 19个程序员接私活平台汇总升级版!你有技术就有钱!
  9. 路由器配置出现192.168.1.0 overlaps with Vlan2的解决方案
  10. 使用urjtag了解WRV54G
  11. 仅用10行Python代码,便可以坐拥后宫3000
  12. 有适合宝妈在家做的兼职推荐吗?5个适合在家做的副业兼职!
  13. 对交换机与路由器的认知
  14. 微信小程序运营系列(八)——怎么玩转中高频行业运营?
  15. pycharm软件中去掉竖线的方法
  16. 加载.npz文件时,出现错误:OSError: Failed to interpret file ‘xxx.npz‘ as a pickle
  17. 机器人唱歌bgm_Soul app里面机器人匹配的那首bgm是什么呀?好好听!!!求玩过soul的大神告知!!...
  18. 未来科技业界的10大风口
  19. 干货丨时序数据库DolphinDB即时编译(JIT)详解
  20. 很简单的安装油猴(tampermonkey)脚本及使用教程

热门文章

  1. 基于LSB的空域信息隐藏实现
  2. jQuery 怎么实现点击页面其他地方隐藏菜单? 做了个按钮点击时弹出菜单,想实现点击其他地方时隐藏弹出的菜单
  3. window10专业版关闭defender
  4. java1.7线程暂停_Java实现多线程断点下载实例代码(下载过程中可以暂停)
  5. NFT + DeFi ,Web3.0去中心化网络时代的下一个风口?
  6. BAT华为等一线大厂Java工程师必读书单
  7. 部署hrm系统-Docker基础环境安装
  8. [音乐]推荐一个听歌网站YOBO
  9. log4js 关于 Appender 的介绍及回滚生成日志文件的方法 “dateFile ”
  10. 数据挖掘之统计学基础(1):【理论】描述性统计