c语言操作mysql数据库,你的小本本又要拿出来了
c语言操作Mysql数据库,主要就是为了实现对数据库的增、删、改、查等操作,操作之前,得先连接数据库啊,而连接数据库主要有两种方法。一、使用mysql本身提供的API,在mysql的安装目录中可可以看到大量的头文件、lib文件、dll文件,这说明mysql原生就支持了c语言,操作起来相当简单。二、使用win32 api(这里只探讨windows平台),主要是ODBC。
ODBC API 接口是(Open Database Connectivity)开放式数据库接口,它建立了一组规范,并提供了一组对数据库访问的标准API,这些API利用SQL来完成其大部分任务。ODBC本身也提供了对SQL语言的支持,用户可以直接将SQL语句送给ODBC。这个基于ODBC的应用程序对数据库的操作不依赖任何DBMS,不直接与DBMS打交道,所有的数据库操作由对应的DBMS的ODBC驱动程序完成。也就是说,不论是FoxPro、Access还是Oracle数据库,均可用ODBC API进行访问。由此可见,ODBC的最大优点是能以统一的方式处理所有的数据库。
功能: 分配或初始化MYSQL对象。
参数:mysql
待初始化的MYSQ对象,将对象地址传入,NULL指针,该函数将分配、初始化、并返回新对象。否则,将初始化对象,并返回对象的地址。
用法实例:
MYSQL mysql;
mysql_init(&mysql); // 或者 mysql = mysql_init(NULL);
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数据库引擎建立连接,这个函数参数很多啊。看名字就可以是什么意思了
参数:mysql 前面一个函数的返回的mysql实例句柄。host 要连接的数据库的主机,可以是ip地址或主机名。user 表示登录数据库的用户名
passwd 登录的密码。db 就是访问的数据库。port mysql的tcp/ip端口默认是3306.unix_socket 表示连接类型。client_flag 暂时为0即可。
3 int mysql_query(MYSQL *mysql,const char *query)
功能:根据query查询语句执行查询数据库
参数: mysql mysql的实例。query 查询语句字符串
返回值: 成功返回0,失败返回非0
4 MYSQL_RES *mysql_store_result(MYSQL *mysql)
功能:得到查询的结果集,对于成功检索了数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN、CHECK TABLE等),必须调用mysql_store_result()或mysql_use_result()
参数:mysql前面的mysql实例
返回值:成功返回MYSQL_RES结构体,该结构体中保存查询的结果
5 MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)
功能:mysql_store_result得到的结果结构中提取一行,并把它放到一个行结构中。
返回值:下一行的一个MYSQL_ROW结构当数据用完或发生错误时返回null
下面是简单实例代码
#include
#include
#include<Windows.h>
#include "C:\Program Files\MySQL\MySQL Server 5.7\include\mysql.h" //包含MySQL所需要的头文件
#pragma comment(lib, "libmysql.lib")
int main(void)
{
MYSQL mysql, *sock; //声明MySQL的句柄
const char * host = "127.0.0.1"; //因为是作为本机测试,所以填写的是本地IP
const char * user = "root"; //这里改为你的用户名,即连接MySQL的用户名
const char * passwd = "root"; //这里改为你的用户密码
const char * db = "test"; //这里改为你要连接的数据库的名字,一个数据可能有几张表
unsigned int port = 3306; //这是MySQL的服务器的端口,如果你没有修改过的话就是3306。
const char * unix_socket = NULL; //unix_socket这是unix下的,我在Windows下,所以就把它设置为NULL
unsigned long client_flag = 0; //这个参数一般为0
const char * i_query = "select * from person"; //查询语句,从那个表中查询,这里后面没有;
MYSQL_RES * result; //保存结果集的
MYSQL_ROW row; //代表的是结果集中的一行
//my_ulonglong row;
mysql_init(&mysql); //连接之前必须使用这个函数来初始化
if ( (sock = mysql_real_connect(&mysql, host, user, passwd, db, port, unix_socket, client_flag) ) == NULL ) //连接MySQL
{
printf("fail to connect mysql \n");
fprintf(stderr, " %s\n", mysql_error(&mysql));
exit(1);
}
else
{
fprintf(stderr, "connect ok!!\n");
}
if ( mysql_query(&mysql, i_query) != 0 ) //如果连接成功,则开始查询 .成功返回0
{
fprintf(stderr, "fail to query!\n");
exit(1);
}
else
{
if ( (result = mysql_store_result(&mysql)) == NULL ) //保存查询的结果
{
fprintf(stderr, "fail to store result!\n");
exit(1);
}
else
{
while ( (row = mysql_fetch_row(result)) != NULL ) //读取结果集中的数据,返回的是下一行。因为保存结果集时,当前的游标在第一行【之前】
{
printf("name is %s\t", row[0]); //打印当前行的第一列的数据
printf("age is %s\t\n", row[1]); //打印当前行的第二列的数据
//row = mysql_num_row(result);
//printf("%lu\n", mysql_num_row(result));
}
}
}
mysql_free_result(result); //释放结果集
mysql_close(sock); //关闭连接
system("pause");
exit(EXIT_SUCCESS);
}
感谢观看!
文章来源于 虎牙来了
C 在MySQL海量数据下的高效读取、写入
前提
由于工作的原因,经常需要对海量数据进行处理,做的数据爬虫相关,动辄千万级别的数据,单表几十个G 都是都是家常便饭。 主要开发语言是C#,数据库使用的是MySQL。
最常见的操作便是select 读取数据,然后在C#中对数据进行处理, 完毕后再插入数据库中。 简而言之就select -> process -> insert 三个步骤。 对于数据量小的情况下(百万级别 or 几百兆)可能
最多1个小时就处理完了。但是对于千万级数据可能几天,甚至更多。 那么问题来了,如何优化??
(数据库的一览,有图有真相)
第一步 解决读取的问题
跟数据库打交道的方式有很多,我来列举下吧:
1. 【重武器-坦克大炮】使用重型ORM框架,比如EF,NHibernat 这样的框架。
2. 【轻武器-AK47】 使用Dapper,PetaPoco 之类,单cs文件。灵活高效,使用简单。居家越货必备(我更喜欢PetaPoco :))
3. 【冷兵器?匕首?】使用原生的Connection、Command。 然后写原生的SQL语句。。
分析:
【重武器】在我们这里肯定直接被PASS, 他们应该被用在大型项目中。
【轻武器】Dapper,PetaPoco 看过源码你会发现用到了反射,虽然使用IL和缓存技术 ,但是还是会影响读取效率,PASS
好吧那就只有使用匕首,原生SQL 走起, 利用DataReader 进行高效读取,并且使用索引 取数据(更快),而不是列名。
大概的代码如下:
using (var conn = new MySqlConnection("Connection String..."))
{
conn.Open(); //此处设置读取的超时,不然在海量数据时很容易超时
var c = new MySqlCommand("set net_write_timeout=9999999; set net_read_timeout=9999999", conn);
c.ExecuteNonQuery();
MySqlCommand rcmd = new MySqlCommand();
rcmd.Connection = conn;
rcmd.CommandText = @"SELECT `f1`,`f2` FROM `table1`"; //设置命令的执行超时
rcmd.CommandTimeout = 99999999; var myData = rcmd.ExecuteReader(); while (myData.Read())
{ var f1= myData.GetInt32(0); var f2= myData.GetString(1); //这里做数据处理.... }
}
哈哈,怎么样,代码非常原始,还是使用索引来取数据,很容易出错。当然一切为了性能咱都忍了
第二步 数据处理
其实这一步,根据你的业务需要,代码肯定不一, 不过无非是一些字符串处理 ,类型转换 的操作,这时候就是考验你的C#基础功底的时候了。 以及如何高效编写正则表达式。。。
具体代码也没法写啊 ,先看完CLR via C# 在来跟我讨论吧 ,O(∩_∩)O哈哈哈~ 跳过。。。。
第三部 数据插入
如何批量插入才最高效呢? 有同学会说, 使用事务 啊,BeginTransaction, 然后EndTransaction。 恩,这个的确可以提高插入效率。 但是还有更加高效的方法,那就是合并insert语句。
那么怎么合并呢?
insert into table (f1,f2) values(1,'sss'),values(2,'bbbb'),values(3,'cccc');
就是把values后面的全部用逗号,链接起来,然后一次性执行 。
当然不能一次性提交个100MB的SQL执行,MySQL服务器对每次执行命令的长度是有限制的。 通过 MySQL服务器端的max_allowed_packet 属性可以查看, 默认是1MB
咱们来看看伪代码吧
//使用StringBuilder高效拼接字符串
var sqlBuilder = new StringBuilder(); //添加insert 语句的头
string sqlHeader = "insert into table1 (`f1`,`f2`) values";
sqlBuilder.Append(sqlHeader); using (var conn = new MySqlConnection("Connection String..."))
{
conn.Open(); //此处设置读取的超时,不然在海量数据时很容易超时
var c = new MySqlCommand("set net_write_timeout=9999999; set net_read_timeout=9999999", conn);
c.ExecuteNonQuery();
MySqlCommand rcmd = new MySqlCommand();
rcmd.Connection = conn;
rcmd.CommandText = @"SELECT `f1`,`f2` FROM `table1`"; //设置命令的执行超时
rcmd.CommandTimeout = 99999999; var myData = rcmd.ExecuteReader(); while (myData.Read())
{ var f1 = myData.GetInt32(0); var f2 = myData.GetString(1); //这里做数据处理....
sqlBuilder.AppendFormat("({0},'{1}'),", f1,AddSlash(f2)); if (sqlBuilder.Length >= 1024 * 1024)//当然这里的1MB length的字符串并不等于 1MB的Packet。。。我知道:)
{
insertCmd.Execute(sqlBuilder.Remove(sqlBuilder.Length-1,1).ToString())//移除逗号,然后执行
sqlBuilder.Clear();//清空
sqlBuilder.Append(sqlHeader);//在加上insert 头 }
}
}
好了,到这里 大概的优化后的高效查询、插入就完成了。
结语
总结下来,无非2个关键技术点,DataReader、SQL合并, 都是一些老的技术啦。
其实,上面的代码只能称得上高效 , 但是, 却非常的不优雅。。。甚至难看。。。
那那么问题来了? 如何进行重构呢? 通过重构抽象出一个可用的类,而不必关心字符串拼接这些乱七八糟的东西,支持多线程合并写入,
最大限度提高写入IO, 我们在下一篇文章中再来谈谈。
有同学来试试封装一个上面的类吗? 看看谁写的最好!
园子里高手如云,欢迎有兴趣的同学一起来讨论 哈哈。
免责声明:文章来源于作者原创或者收集于网络。如果对该文章有任何问题或觉得文章侵权,请及时联系作者修改或删除文章。
相关问答
mysql 与 c 语言的区别?MySQL和C语言是完全不同的概念,它们在以下几个方面有明显的区别:1.类型:-MySQL:MySQL是一种关系型数据库管理系统(RDBMS),用于存储、管理和检...-M...
用纯 C ,写一个类 mysql 存储引擎,难度有多大?mysql是开源的呀你去看看代码看看理解了多少就知道有多难了关系型数据库的难点是事务锁存储引擎SQL语法触发器集群索引等而且还要你的非常可靠...
mysql 下载会占 c 盘多少?Mysql下载安装后,如果还没有创建数据库,那么占用空间一般大约800M左右,当然后续随着你创新新的数据库实例,并录入越来越多的数据,占用空间也会越来越大,而C...
Mysql 里面的blob 字段, 如何用 C 操作?[回答]http://www.xxxx.com/aa.asp?p=xxxhttp://www.xxxx.com/aa.aspx?p=xxxhttp://www.xxxx.com/aa.php?p=xx...
史上最难的 mysql 面试题啊,列 C 的产品,求得它的属性标识和值,...史上最难的mysql面试题啊,列C的产品,求得它的属性标识和值,求大神来解惑啊要考虑效率,比如查询一千个商品,若按照php思维先列产品再循环根据条件又查询...
计算机二级有哪些种类? 申请方[回答]计算机二级考试内容主要有三类,分别为:语言程序设计类,数据库程序设计类,办公软件高级应用。其中,语言程序设计类:C、C++、Java、VisualBasic、Web...
mysql 安装一定要装在 c 盘吗?不一定,也可以装在C盘,方法如下:1、首先在桌面上双击打开“此电脑”软件。2、然后在打开的此电脑页面中,找到并双击打开C盘。3、选中需要移动的文件,再右...
CAS和Moodle成功对接之后,CAS用户是怎样写入 mysql 数据库的?...CAS和Moodle成功对接之后,CAS用户是怎样写入mysql数据库的?Moodle中关于CAS的身份认证插件配置成功之后,让LDAP用户通过CAS登陆认证成功登陆Moodle并写入....
Warning: mysql _fetch_assoc(): supplied argument is not a...[最佳回答]$connect=mysql_connect($server,$username,$password);if(!$connect){die("服务器连接失败:"...
mysql 语句与sqlserver语句转换select*from(SELECTbookid,cou...[最佳回答]其它的应该都差不多,limit10改成top10应该就可以了,大致如下:selecttop10*from(SELECTbookid,count(bookid)asdegreeF...