Linux下C++访问MySQL数据库

时间:2022-03-23 00:14:52

由于要在Linux 下用C++来访问并操作数据库,就在网上搜索了一下,找到了这篇文章,讲的不错,分享一下!

——————————————————————————————————————————————— 

  由于想要开始了解并学习用LAMP进行web开发,所以昨晚我在Fedora上安装了MySQL,学习了MySQL的几个常用命令。想着在学习进行web开发(PHP访问数据库)之前,先用我熟悉的C++连接数据库试试。由于以前只接触过SQL Server,所以在网上查了很多资料,这里记录一下,以备后用。

 一,安装MySQL

    当然在使用MySQL之前,首先需要安装。我的linux发行版是Fedora 20,所以我先在MySQL官网下了一个通用版的MySQL-5.6.17-1.linux_glibc2.5.x86_64.rpm-bundle.rar,然后用归档管理器提取出来以后,发现里面有7个rpm文件,我们要使用MySQL数据库,只需要安装MySQL-serverMySQL-client就行了。具体的安装完了以后的设置密码我就不多说了。安装好了以后,在终端输入mysql -u root -p就可以进入mysql操作环境了。

二,C/C++连接MySQL

     连接MySQL数据库有两种方法:第一种是使用ADO连接,不过这种只适合Windows平台;第二种是使用MySQL自己的C API函数连接数据库。

     这里我们说的就是使用MySQL的C API函数访问MySQL数据库。C API代码是与MySQL一起提供的,它包含在mysqlclient库中,并允许C/C++程序访问数据库。具体的数据类型和函数描述可以去看MySQL官网的MySQL_C_API参考手册

     这里的例子有使用到几个函数:

mysql_init() 获取或初始化MYSQL结构
mysql_real_connect() 连接到MySQL服务器。
mysql_query() 执行指定为“以Null终结的字符串”的SQL查询。
mysql_use_result() 初始化逐行的结果集检索。
mysql_field_count() 返回上次执行语句的结果集的列数。
mysql_fetch_row() 从结果集中获取下一行
mysql_num_fields() 返回结果集中的字段数


示例代码:

[cpp] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. /************************************************************************* 
  2.     > File Name: MyDB.h 
  3.     > Author: SongLee 
  4.     > E-mail: lisong.shine@qq.com 
  5.     > Created Time: 2014年05月04日 星期日 23时25分50秒 
  6.     > Personal Blog: http://songlee24.github.io 
  7.  ************************************************************************/  
  8. #ifndef __MYBD_H__  
  9. #include<iostream>  
  10. #include<string>  
  11. #include<mysql/mysql.h>  
  12. using namespace std;  
  13.   
  14. class MyDB  
  15. {  
  16. public:  
  17.     MyDB();  
  18.     ~MyDB();  
  19.     bool initDB(string host, string user, string pwd, string db_name);  
  20.     bool exeSQL(string sql);  
  21. private:  
  22.     MYSQL *connection;  
  23.     MYSQL_RES *result;  
  24.     MYSQL_ROW row;  
  25. };  
  26.   
  27. #endif  

[cpp] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. /************************************************************************* 
  2.     > File Name: MyDB.cpp 
  3.     > Author: SongLee 
  4.     > E-mail: lisong.shine@qq.com 
  5.     > Created Time: 2014年05月04日 星期日 23时37分08秒 
  6.     > Personal Blog: http://songlee24.github.io 
  7.  ************************************************************************/  
  8. #include<iostream>  
  9. #include<cstdlib>  
  10. #include "MyDB.h"  
  11. using namespace std;  
  12.   
  13. MyDB::MyDB()  
  14. {  
  15.     connection = mysql_init(NULL); // 初始化数据库连接变量  
  16.     if(connection == NULL)  
  17.     {  
  18.         cout << "Error:" << mysql_error(connection);  
  19.         exit(1);  
  20.     }  
  21. }  
  22.   
  23. MyDB::~MyDB()  
  24. {  
  25.     if(connection != NULL)  // 关闭数据库连接  
  26.     {  
  27.         mysql_close(connection);  
  28.     }  
  29. }  
  30.   
  31. bool MyDB::initDB(string host, string user, string pwd, string db_name)  
  32. {  
  33.     // 函数mysql_real_connect建立一个数据库连接  
  34.     // 成功返回MYSQL*连接句柄,失败返回NULL  
  35.     connection = mysql_real_connect(connection, host.c_str(),  
  36.             user.c_str(), pwd.c_str(), db_name.c_str(), 0, NULL, 0);  
  37.     if(connection == NULL)  
  38.     {  
  39.         cout << "Error:" << mysql_error(connection);  
  40.         exit(1);  
  41.     }  
  42.     return true;  
  43. }  
  44.   
  45. bool MyDB::exeSQL(string sql)  
  46. {  
  47.     // mysql_query()执行成功返回0,失败返回非0值。与PHP中不一样  
  48.     if(mysql_query(connection, sql.c_str()))  
  49.     {  
  50.         cout << "Query Error:" << mysql_error(connection);  
  51.         exit(1);  
  52.     }  
  53.     else  
  54.     {  
  55.         result = mysql_use_result(connection); // 获取结果集  
  56.         // mysql_field_count()返回connection查询的列数  
  57.         for(int i=0; i < mysql_field_count(connection); ++i)  
  58.         {  
  59.             // 获取下一行  
  60.             row = mysql_fetch_row(result);  
  61.             if(row <= 0)  
  62.             {  
  63.                 break;  
  64.             }  
  65.             // mysql_num_fields()返回结果集中的字段数  
  66.             for(int j=0; j < mysql_num_fields(result); ++j)  
  67.             {  
  68.                 cout << row[j] << " ";  
  69.             }  
  70.             cout << endl;  
  71.         }  
  72.         // 释放结果集的内存  
  73.         mysql_free_result(result);  
  74.     }  
  75.     return true;  
  76. }  


[cpp] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. /************************************************************************* 
  2.     > File Name: main.cpp 
  3.     > Author: SongLee 
  4.     > E-mail: lisong.shine@qq.com 
  5.     > Created Time: 2014年05月05日 星期一 00时30分45秒 
  6.     > Personal Blog: http://songlee24.github.io 
  7.  ************************************************************************/  
  8. #include<iostream>  
  9. #include "MyDB.h"  
  10. using namespace std;  
  11.   
  12. int main()  
  13. {  
  14.     MyDB db;  
  15.     db.initDB("localhost""root""songlee""student");  
  16.     db.exeSQL("select * from student_info");  
  17.     return 0;  
  18. }  

基本步骤就是:

  • 使用mysql_init()初始化连接
  • 使用mysql_real_connect()建立一个到mysql数据库的连接
  • 使用mysql_query()执行查询语句
  • result = mysql_use_result(conn)获取结果集
  • mysql_field_count(conn)获取查询的列数,mysql_num_fields(result)获取结果集的字段数
  • 通过mysql_fetch_row(result)不断获取下一行,然后循环输出
  • 释放结果集所占内存mysql_free_result(result)
  • mysql_close(conn)关闭连接

三,创建所需数据库

     通过C++查询数据库的数据,当然你得创建所需数据库,可以通过代码创建,也可以在终端创建数据库。首先通过用户名和密码进入mysql:

[plain] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. mysql -u root -p  
1,查看所有数据库:

[sql] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. mysql> show databases;  
  2. +--------------------+  
  3. Database           |  
  4. +--------------------+  
  5. | information_schema |  
  6. | mysql              |  
  7. | performance_schema |  
  8. | test               |  
  9. +--------------------+  
  10. rows in set (0.00 sec)  
MySQL默认有自带的数据库,mysql库存放着mysql的系统和用户权限信息,我们改密码和新增用户,实际上就是对这个库进行操作。

2,创建数据库:

[sql] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. mysql> CREATE DATABASE student;  
  2. Query OK, 1 row affected (0.00 sec)  

3,建表:

[sql] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. mysql> CREATE TABLE student_info(  
  2.     -> stu_num CHAR(20) NOT NULL,  
  3.     -> stu_name CHAR(10) NOT NULL,  
  4.     -> stu_age int NOT NULL,  
  5.     -> stu_grade CHAR(5) NOT NULL,  
  6.     -> stu_score int,  
  7.     -> PRIMARY KEY(stu_num));  
  8. Query OK, 0 rows affected (0.38 sec)  

4,查看所有数据表

[sql] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. mysql> use student;  
  2. Database changed  
  3. mysql> show tables;  
  4. +-------------------+  
  5. | Tables_in_student |  
  6. +-------------------+  
  7. | student_info      |  
  8. +-------------------+  
  9. 1 row in set (0.00 sec)  

5,查看数据表的结构(字段)

[sql] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. mysql> describe student_info;  
  2. +-----------+----------+------+-----+---------+-------+  
  3. | Field     | Type     | Null | Key | Default | Extra |  
  4. +-----------+----------+------+-----+---------+-------+  
  5. | stu_num   | char(20) | NO   | PRI | NULL    |       |  
  6. | stu_name  | char(10) | NO   |     | NULL    |       |  
  7. | stu_age   | int(11)  | NO   |     | NULL    |       |  
  8. | stu_grade | char(5)  | NO   |     | NULL    |       |  
  9. | stu_score | int(11)  | YES  |     | NULL    |       |  
  10. +-----------+----------+------+-----+---------+-------+  
  11. rows in set (0.10 sec)  

6,插入数据

[sql] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. mysql> INSERT INTO student_info VALUES("U201018113""SongLee", 23, "1007", 85);   
  2. Query OK, 1 row affected (0.10 sec)  

7,查询数据

[sql] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. mysql> SELECT * FROM student_info;  
  2. +------------+----------+---------+-----------+-----------+  
  3. | stu_num    | stu_name | stu_age | stu_grade | stu_score |  
  4. +------------+----------+---------+-----------+-----------+  
  5. | U201018113 | SongLee  |      23 | 1007      |        85 |  
  6. +------------+----------+---------+-----------+-----------+  
  7. 1 row in set (0.00 sec)  

四,运行程序获取MySQL数据库数据

      下面来编译运行上面的示例代码,首先进行编译,我写了一个Makefile文件:

[plain] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. mydb:main.cpp MyDB.cpp  
  2.     g++ -o mydb main.cpp MyDB.cpp  
注意,g++前面是tab而不是空格。然后在终端输入make,回车。出现了错误:

[plain] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. [songlee@localhost ~]$ make  
  2. g++ -o mydb main.cpp MyDB.cpp  
  3. In file included from main.cpp:9:0:  
  4. MyDB.h:11:18: 致命错误:mysql.h:没有那个文件或目录  
  5.  #include<mysql/mysql.h>  
  6.                   ^  
  7. 编译中断。  
  8. In file included from MyDB.cpp:10:0:  
  9. MyDB.h:11:18: 致命错误:mysql.h:没有那个文件或目录  
  10.  #include<mysql/mysql.h>  
  11.                   ^  
  12. 编译中断。  
  13. make: *** [mydb] 错误 1  

找不到mysql.h头文件。。。于是除了MySQL-server-和MySQL-client-之外,我又安装了devel和shared包:

[plain] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. sudo rpm -ivh MySQL-devel-5.6.17-1.linux_glibc2.5.x86_64.rpm  
  2. sudo rpm -ivh MySQL-shared-5.6.17-1.linux_glibc2.5.x86_64.rpm  

再make一次,mysql.h头文件找到了,但是又出现了问题:

[plain] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. [songlee@localhost ~]$ make  
  2. g++ -o mydb main.cpp MyDB.cpp  
  3. /tmp/cc9ZZHBx.o:在函数‘MyDB::MyDB()’中:  
  4. MyDB.cpp:(.text+0x13):对‘mysql_init’未定义的引用  
  5. MyDB.cpp:(.text+0x35):对‘mysql_error’未定义的引用  
  6. /tmp/cc9ZZHBx.o:在函数‘MyDB::~MyDB()’中:  
  7. MyDB.cpp:(.text+0x8b):对‘mysql_close’未定义的引用  
  8. /tmp/cc9ZZHBx.o:在函数‘MyDB::initDB(std::string, std::string, std::string, std::string)’中:  
  9. MyDB.cpp:(.text+0x11a):对‘mysql_real_connect’未定义的引用  
  10. MyDB.cpp:(.text+0x13c):对‘mysql_error’未定义的引用  
  11. /tmp/cc9ZZHBx.o:在函数‘MyDB::exeSQL(std::string)’中:  
  12. MyDB.cpp:(.text+0x1a6):对‘mysql_query’未定义的引用  
  13. MyDB.cpp:(.text+0x1be):对‘mysql_error’未定义的引用  
  14. MyDB.cpp:(.text+0x1f4):对‘mysql_use_result’未定义的引用  
  15. MyDB.cpp:(.text+0x218):对‘mysql_fetch_row’未定义的引用  
  16. MyDB.cpp:(.text+0x284):对‘mysql_num_fields’未定义的引用  
  17. MyDB.cpp:(.text+0x2b2):对‘mysql_field_count’未定义的引用  
  18. MyDB.cpp:(.text+0x2cf):对‘mysql_free_result’未定义的引用  
  19. collect2: 错误:ld 返回 1  
  20. make: *** [mydb] 错误 1  

找到了头文件,但是相关函数都未定义,原因是因为没有链接需要的库libmysqlclient.so,终端输入命令 mysql_config --libs

[plain] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. [songlee@localhost ~]$ mysql_config --libs  
  2. -L/usr/lib64 -lmysqlclient -lpthread -lm -lrt -ldl  

将选项 -L/usr/lib64 -lmysqlclient加入gcc/g++命令中,即修改Makefile文件为:

[plain] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. mydb:main.cpp MyDB.cpp  
  2.     g++ -L/usr/lib64 -lmysqlclient -o mydb main.cpp MyDB.cpp  
再次make成功了,运行程序:

[plain] view plaincopyprint?Linux下C++访问MySQL数据库Linux下C++访问MySQL数据库
  1. [songlee@localhost ~]$ make  
  2. g++ -L/usr/lib64 -lmysqlclient -o mydb main.cpp MyDB.cpp  
  3. [songlee@localhost ~]$ ./mydb   
  4. U201018113 SongLee 23 1007 85   

这样,MySQL数据库访问成功!