由于想要开始了解并学习用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() 返回结果集中的字段数

示例代码:

  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
  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. }
  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:

  1. mysql -u root -p

1,查看所有数据库:

  1. mysql> show databases;
  2. +--------------------+
  3. | Database |
  4. +--------------------+
  5. | information_schema |
  6. | mysql |
  7. | performance_schema |
  8. | test |
  9. +--------------------+
  10. 4 rows in set (0.00 sec)

MySQL默认有自带的数据库,mysql库存放着mysql的系统和用户权限信息,我们改密码和新增用户,实际上就是对这个库进行操作。

2,创建数据库:

  1. mysql> CREATE DATABASE student;
  2. Query OK, 1 row affected (0.00 sec)

3,建表:

  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,查看所有数据表

  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,查看数据表的结构(字段)

  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. 5 rows in set (0.10 sec)

6,插入数据

  1. mysql> INSERT INTO student_info VALUES("U201018113", "SongLee", 23, "1007", 85);
  2. Query OK, 1 row affected (0.10 sec)

7,查询数据

  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文件:

  1. mydb:main.cpp MyDB.cpp
  2. g++ -o mydb main.cpp MyDB.cpp

注意,g++前面是tab而不是空格。然后在终端输入make,回车。出现了错误:

  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包:

  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头文件找到了,但是又出现了问题:

  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

  1. [songlee@localhost ~]$ mysql_config --libs
  2. -L/usr/lib64 -lmysqlclient -lpthread -lm -lrt -ldl

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

  1. mydb:main.cpp MyDB.cpp
  2. g++ -L/usr/lib64 -lmysqlclient -o mydb main.cpp MyDB.cpp

再次make成功了,运行程序:

  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数据库访问成功!

Linux下C++访问MySQL数据库的更多相关文章

  1. Linux下自动备份MySQL数据库并上传到远程FTP服务器

    Linux下自动备份MySQL数据库并上传到远程FTP服务器且删除指定日期前的备份Shell脚本 说明:  1.备份MySQL数据库存放目录/var/lib/mysql下面的xshelldata数据库 ...

  2. Linux下定时备份MySQL数据库的Shell脚本

    Linux下定时备份MySQL数据库的Shell脚本   对任何一个已经上线的网站站点来说,数据备份都是必须的.无论版本更新还是服务器迁移,备份数据的重要性不言而喻.人工备份数据的方式不单耗费大量时间 ...

  3. Linux下C连接MySql数据库

    目录: 一.解决小的问题: 二.大问题,如果你不小心把/usr/lib的所属用户改了导致sudo命令用不了: 三.C连接MySql编程本身: 其实写这个程序真的很简单,十多分钟的事情,只是以前没在Li ...

  4. Linux下远程连接MySQL数据库

    估计搞了一个多小时才把这个远程连接搞好.一台本地电脑,一台云服务器,都是linux系统. 步骤 在服务器端开启远程访问 首先进入mysql数据库,然后输入下面两个命令: grant all privi ...

  5. Linux下如何启用MySQL数据库远程访问

    远程连接MySQL出于安全考虑,一般都关闭了远程访问,但有时候需要提供远程访问数据库的服务,下面我们快速学习下: 第一步:修改my.cnf文件使用文本编辑器去编辑MySQL服务器的配置文件my.cnf ...

  6. linux 下C++查询mysql数据库

    上一节我们看了怎么使用mysql提供的API来连接mysql数据库,现在来看看怎么执行一条简单的查询语句,并且把查询的结果显示出来. 准备工作:首先新建了一个数据库inote,在这个数据库下面新建了一 ...

  7. Linux下C++连MySQL数据库

    1.查看本地有没有安装mysql,命令就是mysql,如果有这个命令就表示安装了mysql数据库软件.如果没有就自行安装. MySQL-server-4.0.16-0.i386.rpm MySQL-c ...

  8. Linux下如何从mysql数据库里导出导入数据

    https://blog.csdn.net/u012884402/article/details/47337701 一. 表的导入 1.进入数据库 mysql 数据库名 2.​查看表 show tab ...

  9. Linux下第一次使用MySQL数据库,设置密码

    在终端下输入:/etc/rc.d/init.d/mysqld status 查看MySQL状态,看看是否运行. 没有运行的话就输入:/etc/rc.d/init.d/mysqld start 这时,就 ...

随机推荐

  1. CF816B Karen and Coffee

    思路: 有点类似于区间修改点查询的树状数组. 实现: #include <iostream> #include <cstdio> using namespace std; ; ...

  2. AndroidStudio3.0 Canary 8注解报错Annotation processors must be explicitly declared now.

    体验最新版AndroidStudio3. Canary 8的时候,发现之前项目的butter knife报错,用到注解的应该都会报错 Error:Execution failed for task ' ...

  3. Selenium学习第二天,了解Selenium工作模式与学习Selenium需要具备的知识与工具。

    Selenium学习网站: 1.http://www.ltesting.net/ceshi/open/kygncsgj/selenium/2014/0408/207237.html——好像是对API的 ...

  4. 循环插入记录,id每次加1

    sql语句写法: begin for i in 1 .. 100 loop insert into table_name values(....); end loop; commit; end; 例子 ...

  5. JS中的let和var的区别

    最近很多前端的朋友去面试被问到let和var的区别,其实阮一峰老师的ES6中已经很详细介绍了let的用法和var的区别.我简单总结一下,以便各位以后面试中使用. ES6 新增了let命令,用来声明局部 ...

  6. A useful logger function in C project.

    #cat log.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include < ...

  7. win10 javac无效

    win10配置环境变量时,要写绝对路径,不再需要写JAVA_HOME和classpaht,直接在pass上添加全路径就可以了.

  8. Linux之iptables(六、rich规则)

    其它规则 当基本firewalld语法规则不能满足要求时,可以使用以下更复杂的规则 rich-rules 富规则,功能强,表达性语言 Direct configuration rules 直接规则,灵 ...

  9. Yii 时间日期组件与composer 下载中出现的问题

    首先本篇主要讲3点 一个Yii时间日期组件的两种用法 笔者使用composer下载该组件时出现问题的解决办法 1.composer下载出现的问题 file could not be downloade ...

  10. 关于JavaScript的一些笔试题

    1.原题: function Foo() { getName = function () { alert (); }; return this; } Foo.getName = function () ...