您的位置:首页 > 运维架构 > Linux

linux下c++连接mysql数据库

2017-07-21 22:07 549 查看
在Linux下,我们可以通过MySQL提供的C API连接数据库。

使用C API连接mysql数据库除了要安装mysql-client和mysql-server,还需要安装mysql的开发包mysql-devel。

我的系统是fedora,安装命令如下:
sudo yum install mysql-devel


ubuntu下安装命令:
sudo apt-get install libmysqld-dev


然后加上<mysql/mysql.h>头文件就可以使用了。

想要具体了解C API函数的可以参考官方文档:官方mysql C API函数说明

我们在这里只介绍一些常用到的函数,以及将它们用c++封装起来,方便使用。

常用函数:

函数说明
MYSQL *mysql_init(MYSQL *mysql)获取或初始化MYSQL结构
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服务器。
int mysql_query(MYSQL *mysql, const char *stmt_str)执行指定为“以Null终结的字符串”的SQL查询。
MYSQL_RES *mysql_store_result(MYSQL *mysql)将查询的整个结果读取到客户端,分配一个 MYSQL_RES结构,并将结果放入此结构中
unsigned int mysql_field_count(MYSQL *mysql)返回上次执行语句的结果集的列数。
unsigned int mysql_num_fields(MYSQL_RES *result)返回结果集中的列数。
my_ulonglong mysql_num_rows(MYSQL_RES *result)返回结果集中的行数。
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)从结果集中获取下一行数据
void mysql_free_result(MYSQL_RES *result)释放结果集空间

相关数据结构:

MYSQL结构体

此结构表示一个数据库连接的处理程序。它几乎用于所有MySQL功能。

MYSQL_RES结构体

存储查询结果数据。

MYSQL_ROW结构体

存储一行数据的结构。

相关函数的介绍:

1.mysql_init()

分配或初始化MYSQL适合的对象 mysql_real_connect()。如果 mysql是NULL指针,则该函数分配,初始化并返回一个新对象。否则,对象被初始化并返回对象的地址。如果 mysql_init()分配一个新的对象,当mysql_close()被调用来关闭该连接时它被释放 。如果没有足够的内存分配一个新对象,则返回NULL。

2. mysql_query()

执行指定为“以Null终结的字符串”的SQL查询。查询成功返回0,失败返回非0值。

3.mysql_field_count()

返回连接上最近查询的列数。

这个函数的正常使用是 mysql_store_result()返回 NULL(因此你没有结果集指针)。在这种情况下,您可以调用 mysql_field_count()确定是否 mysql_store_result()应该产生非空结果。这使得客户端程序能够在不知道查询是SELECT(或 类似SELECT))语句的情况下采取适当的操作。此处显示的示例说明了如何完成此操作。如果不理解的话,看完后面的代码示例就理解了。

基本步骤就是:

使用mysql_init()初始化连接

使用mysql_real_connect()建立一个到mysql数据库的连接

使用mysql_query()执行查询语句

result = mysql_store_result(mysql)获取结果集

mysql_num_fields(result)获取查询的列数,mysql_num_rows(result)获取结果集的行数

通过mysql_fetch_row(result)不断获取下一行,然后循环输出

释放结果集所占内存mysql_free_result(result)

mysql_close(conn)关闭连接

为了使用方便,我用c++进行了简单的封装:MyDB.h和MyDB.CPP

MyDB.h

/*************************************************************************
> File Name: mydb.h
> Author:fengxin
> Mail:903087053@qq.com
> Created Time: 2017年07月21日 星期五 15时17分17秒
************************************************************************/

#ifndef _MYDB_H
#define _MYDB_H
#include<iostream>
#include<string>
#include<mysql/mysql.h>
using namespace std;

class MyDB
{
public:
MyDB();
~MyDB();
bool initDB(string host,string user,string pwd,string db_name); //连接mysql
bool exeSQL(string sql);   //执行sql语句
private:
MYSQL *mysql;          //连接mysql句柄指针
MYSQL_RES *result;    //指向查询结果的指针
MYSQL_ROW row;       //按行返回的查询信息
};

#endif


MyDB.cpp

/*************************************************************************
> File Name: MyDB.cpp
> Author:fengxin
> Mail:903087053@qq.com
> Created Time: 2017年07月21日 星期五 16时02分51秒
************************************************************************/

#include<iostream>
#include<string>
#include "MyDB.h"

using namespace std;

MyDB::MyDB()
{
mysql=mysql_init(NULL);   //初始化数据库连接变量
if(mysql==NULL)
{
cout<<"Error:"<<mysql_error(mysql);
exit(1);
}
}

MyDB::~MyDB()
{
if(mysql!=NULL)  //关闭数据连接
{
mysql_close(mysql);
}
}

bool MyDB::initDB(string host,string user,string passwd,string db_name)
{
// 函数mysql_real_connect建立一个数据库连接
// 成功返回MYSQL*连接句柄,失败返回NULL
mysql = mysql_real_connect(mysql, host.c_str(), user.c_str(), passwd.c_str(), db_name.c_str(), 0, NULL, 0);
if(mysql == NULL)
{
cout << "Error: " << mysql_error(mysql);
exit(1);
}
return true;
}

bool MyDB::exeSQL(string sql)
{
//mysql_query()执行成功返回0,执行失败返回非0值。
if (mysql_query(mysql,sql.c_str()))
{
cout<<"Query Error: "<<mysql_error(mysql);
return false;
}
else // 查询成功
{
result = mysql_store_result(mysql);  //获取结果集
if (result)  // 返回了结果集
{
int  num_fields = mysql_num_fields(result);   //获取结果集中总共的字段数,即列数
int  num_rows=mysql_num_rows(result);       //获取结果集中总共的行数
for(int i=0;i<num_rows;i++) //输出每一行
{
//获取下一行数据
row=mysql_fetch_row(result);
if(row<0) break;

for(int j=0;j<num_fields;j++)  //输出每一字段
{
cout<<row[j]<<"\t\t";
}
cout<<endl;
}

}
else  // result==NULL
{
if(mysql_field_count(mysql) == 0)   //代表执行的是update,insert,delete类的非查询语句
{
// (it was not a SELECT)
int num_rows = mysql_affected_rows(mysql);  //返回update,insert,delete影响的行数
}
else // error
{
cout<<"Get result error: "<<mysql_error(mysql);
return false;
}
}
}

return true;

}


编译:

编译时,记得在末尾加上

`mysql_config --cflags --libs`


才能编译通过。

例如:

g++ MyDB.cpp test.cpp  -o test    `mysql_config --cflags --libs`


使用示例:

测试的例子是,创建一个test数据库,向数据库里的记录用户帐号密码的accounts表中添加和查询数据。

首先,我们在终端下登录数据库,创建一个test数据库,并创建一个名为accounts的表。

mysql -u root -p

Enter password:

Welcome to the MySQL monitor.

mysql>create database test;

Query OK, 1 row affected (0.00 sec)

mysql>use test;

Database changed

mysql>create table accounts(name char(20) not null primary key,passwd char(20) not null);

Query OK, 0 rows affected (0.52 sec)

mysql>exit;

相关的表创建完成,接下来通过test.cpp来向数据库中添加两条用户帐号的信息并将它读取出来。

代码如下:

/*************************************************************************
> File Name: test.cpp
> Author:fengxin
> Mail:903087053@qq.com
> Created Time: 2017年07月21日 星期五 16时43分55秒
************************************************************************/

#include<iostream>
#include"MyDB.h"
using namespace std;

int main()
{
MyDB db;
//连接数据库
db.initDB("localhost","root","fengxin","test");
//将用户信息添加到数据库
db.exeSQL("INSERT accounts values('fengxin','123');");
db.exeSQL("INSERT accounts values('axin','456');");
//将所有用户信息读出,并输出。
db.exeSQL("SELECT * from accounts;");

return 0;
}


我写了一个简单的Makefile,编译起来更加方便。

test:test.cpp MyDB.cpp
g++ test.cpp MyDB.cpp -o test `mysql_config --cflags --libs`


然后执行make,并运行test。

运行结果如下:

./test

axin 456

fengxin 123

通过终端连接数据库查看accounts表的内容,我们看到的结果也是一样的。

mysql> select * from accounts;
+---------+--------+
| name    | passwd |
+---------+--------+
| axin    | 456    |
| fengxin | 123    |
+---------+--------+
2 rows in set (0.00 sec)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: