zoukankan      html  css  js  c++  java
  • Linux下C++访问MySQL数据库

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


    示例代码:

    /*************************************************************************
        > File Name: MyDB.h
        > Author: SongLee
        > E-mail: lisong.shine@qq.com
        > Created Time: 2014年05月04日 星期日 23时25分50秒
        > Personal Blog: http://songlee24.github.io
     ************************************************************************/
    #ifndef __MYBD_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);
    	bool exeSQL(string sql);
    private:
    	MYSQL *connection;
    	MYSQL_RES *result;
    	MYSQL_ROW row;
    };
    
    #endif

    /*************************************************************************
        > File Name: MyDB.cpp
        > Author: SongLee
        > E-mail: lisong.shine@qq.com
        > Created Time: 2014年05月04日 星期日 23时37分08秒
        > Personal Blog: http://songlee24.github.io
     ************************************************************************/
    #include<iostream>
    #include<cstdlib>
    #include "MyDB.h"
    using namespace std;
    
    MyDB::MyDB()
    {
    	connection = mysql_init(NULL); // 初始化数据库连接变量
    	if(connection == NULL)
    	{
    		cout << "Error:" << mysql_error(connection);
    		exit(1);
    	}
    }
    
    MyDB::~MyDB()
    {
    	if(connection != NULL)  // 关闭数据库连接
    	{
    		mysql_close(connection);
    	}
    }
    
    bool MyDB::initDB(string host, string user, string pwd, string db_name)
    {
    	// 函数mysql_real_connect建立一个数据库连接
    	// 成功返回MYSQL*连接句柄,失败返回NULL
    	connection = mysql_real_connect(connection, host.c_str(),
    			user.c_str(), pwd.c_str(), db_name.c_str(), 0, NULL, 0);
    	if(connection == NULL)
    	{
    		cout << "Error:" << mysql_error(connection);
    		exit(1);
    	}
    	return true;
    }
    
    bool MyDB::exeSQL(string sql)
    {
    	// mysql_query()执行成功返回0,失败返回非0值。与PHP中不一样
    	if(mysql_query(connection, sql.c_str()))
    	{
    		cout << "Query Error:" << mysql_error(connection);
    		exit(1);
    	}
    	else
    	{
    		result = mysql_use_result(connection); // 获取结果集
    		// mysql_field_count()返回connection查询的列数
    		for(int i=0; i < mysql_field_count(connection); ++i)
    		{
    			// 获取下一行
    			row = mysql_fetch_row(result);
    			if(row <= 0)
    			{
    				break;
    			}
    			// mysql_num_fields()返回结果集中的字段数
    			for(int j=0; j < mysql_num_fields(result); ++j)
    			{
    				cout << row[j] << " ";
    			}
    			cout << endl;
    		}
    		// 释放结果集的内存
    		mysql_free_result(result);
    	}
    	return true;
    }


    /*************************************************************************
        > File Name: main.cpp
        > Author: SongLee
        > E-mail: lisong.shine@qq.com
        > Created Time: 2014年05月05日 星期一 00时30分45秒
        > Personal Blog: http://songlee24.github.io
     ************************************************************************/
    #include<iostream>
    #include "MyDB.h"
    using namespace std;
    
    int main()
    {
    	MyDB db;
    	db.initDB("localhost", "root", "songlee", "student");
    	db.exeSQL("select * from student_info");
    	return 0;
    }

    基本步骤就是:

    • 使用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:

     mysql -u root -p
    1,查看所有数据库:

    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | test               |
    +--------------------+
    4 rows in set (0.00 sec)
    MySQL默认有自带的数据库,mysql库存放着mysql的系统和用户权限信息,我们改密码和新增用户,实际上就是对这个库进行操作。

    2,创建数据库:

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

    3,建表:

    mysql> CREATE TABLE student_info(
        -> stu_num CHAR(20) NOT NULL,
        -> stu_name CHAR(10) NOT NULL,
        -> stu_age int NOT NULL,
        -> stu_grade CHAR(5) NOT NULL,
        -> stu_score int,
        -> PRIMARY KEY(stu_num));
    Query OK, 0 rows affected (0.38 sec)
    

    4,查看所有数据表

    mysql> use student;
    Database changed
    mysql> show tables;
    +-------------------+
    | Tables_in_student |
    +-------------------+
    | student_info      |
    +-------------------+
    1 row in set (0.00 sec)
    

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

    mysql> describe student_info;
    +-----------+----------+------+-----+---------+-------+
    | Field     | Type     | Null | Key | Default | Extra |
    +-----------+----------+------+-----+---------+-------+
    | stu_num   | char(20) | NO   | PRI | NULL    |       |
    | stu_name  | char(10) | NO   |     | NULL    |       |
    | stu_age   | int(11)  | NO   |     | NULL    |       |
    | stu_grade | char(5)  | NO   |     | NULL    |       |
    | stu_score | int(11)  | YES  |     | NULL    |       |
    +-----------+----------+------+-----+---------+-------+
    5 rows in set (0.10 sec)
    

    6,插入数据

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

    7,查询数据

    mysql> SELECT * FROM student_info;
    +------------+----------+---------+-----------+-----------+
    | stu_num    | stu_name | stu_age | stu_grade | stu_score |
    +------------+----------+---------+-----------+-----------+
    | U201018113 | SongLee  |      23 | 1007      |        85 |
    +------------+----------+---------+-----------+-----------+
    1 row in set (0.00 sec)

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

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

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

    [songlee@localhost ~]$ make
    g++ -o mydb main.cpp MyDB.cpp
    In file included from main.cpp:9:0:
    MyDB.h:11:18: 致命错误:mysql.h:没有那个文件或目录
     #include<mysql/mysql.h>
                      ^
    编译中断。
    In file included from MyDB.cpp:10:0:
    MyDB.h:11:18: 致命错误:mysql.h:没有那个文件或目录
     #include<mysql/mysql.h>
                      ^
    编译中断。
    make: *** [mydb] 错误 1

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

    sudo rpm -ivh MySQL-devel-5.6.17-1.linux_glibc2.5.x86_64.rpm
    sudo rpm -ivh MySQL-shared-5.6.17-1.linux_glibc2.5.x86_64.rpm

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

    [songlee@localhost ~]$ make
    g++ -o mydb main.cpp MyDB.cpp
    /tmp/cc9ZZHBx.o:在函数‘MyDB::MyDB()’中:
    MyDB.cpp:(.text+0x13):对‘mysql_init’未定义的引用
    MyDB.cpp:(.text+0x35):对‘mysql_error’未定义的引用
    /tmp/cc9ZZHBx.o:在函数‘MyDB::~MyDB()’中:
    MyDB.cpp:(.text+0x8b):对‘mysql_close’未定义的引用
    /tmp/cc9ZZHBx.o:在函数‘MyDB::initDB(std::string, std::string, std::string, std::string)’中:
    MyDB.cpp:(.text+0x11a):对‘mysql_real_connect’未定义的引用
    MyDB.cpp:(.text+0x13c):对‘mysql_error’未定义的引用
    /tmp/cc9ZZHBx.o:在函数‘MyDB::exeSQL(std::string)’中:
    MyDB.cpp:(.text+0x1a6):对‘mysql_query’未定义的引用
    MyDB.cpp:(.text+0x1be):对‘mysql_error’未定义的引用
    MyDB.cpp:(.text+0x1f4):对‘mysql_use_result’未定义的引用
    MyDB.cpp:(.text+0x218):对‘mysql_fetch_row’未定义的引用
    MyDB.cpp:(.text+0x284):对‘mysql_num_fields’未定义的引用
    MyDB.cpp:(.text+0x2b2):对‘mysql_field_count’未定义的引用
    MyDB.cpp:(.text+0x2cf):对‘mysql_free_result’未定义的引用
    collect2: 错误:ld 返回 1
    make: *** [mydb] 错误 1

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

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

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

    mydb:main.cpp MyDB.cpp
    	g++ -L/usr/lib64 -lmysqlclient -o mydb main.cpp MyDB.cpp
    再次make成功了,运行程序:

    [songlee@localhost ~]$ make
    g++ -L/usr/lib64 -lmysqlclient -o mydb main.cpp MyDB.cpp
    [songlee@localhost ~]$ ./mydb 
    U201018113 SongLee 23 1007 85 

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


  • 相关阅读:
    14款响应式布局的前端开发框架
    如何在本地进行微信公众号的开发调试
    微信公众帐号应用开发—本地调试
    利用H5开发微信公众号
    微信公众平台开发入门教程
    JAVA编程不得不看的几本经典书籍
    使用百度UMeditor富文本编辑器,修改自定义图片上传,修改源码
    网站建设需要哪些程序
    Visual Studio 2013 中使用断点
    Objective-c 实例变量的访问级别
  • 原文地址:https://www.cnblogs.com/songlee/p/5738152.html
Copyright © 2011-2022 走看看