zoukankan      html  css  js  c++  java
  • C++ MySQL连接及增删改查操作

    一、使用准备

    环境:CentOS 7.6和Ubuntu 16.04,MySQL 5.7

    C++ MySQL连接相关库下载

    下载地址:MySQL Community Downloads

    有两种选择,C API和Connector/C++,貌似C API简单一点,Connector/C++比较规范,和Java JDBC接口一致。这里选择C API

    翻译一下:

    C API(libmysqlclient)是用于C开发的客户端库:

    对于C语言和SQL:

      - 适用于MySQL 8.0、5.7、5.6、5.5

      - 我们建议使用MySQL 8.0 C API

    C API(libmysqlclient)包含在MySQL 8.0中(其他版本也可以在其安装文件夹中找到,通过某些特殊手段安装的可能就没有)

    Linux:可从MySQL Community Server下载页面获得Client Utilities Package

    Repos: 可以从 YumAPTSuSE 仓库获得Client Utilities Package

    Windows:可从Windows Installer获得Client Utilities Package

    以前的GA版本可从MySQL Product Archives中获得

    在线文档地址:MySQL C API

    翻到C API在线文档查看其使用说明:

    该文档说明了如何在Linux上编译MySQL客户端。请仔细阅读,比如使用gcc编译器,注意:以下部分均复制自官方文档,为求准确,建议浏览官方文档原文

    1、引用头文件:

    编译使用MySQL头文件的客户端程序时,可能需要指定-I选项,以便编译器可以找到它们。例如,如果头文件安装在 /usr /local/mysql/include 中,请在compile命令中使用以下选项:

    -I/usr/local/mysql/include

    2、链接库文件

    您可以将代码与动态或静态MySQL C客户端库链接。动态库的基本名称为libmysqlclient,后缀因平台而异(例如,对于Linux为.so,对于macOS为.dylib)。在所有平台上,静态库均名为libmysqlclient.a。

    必须使用link命令中的-lmysqlclient选项链接MySQL客户端。您可能还需要指定-L选项,以告知链接器在哪里可以找到该库。例如,如果该库安装在/usr/local/mysql/lib中,请在链接命令中使用以下选项:

    -L/usr/local/mysql/lib -lmysqlclient

    路径名称在您的系统上可能有所不同。根据需要调整-I和-L选项。

    为了使在Unix上编译MySQL程序更简单,请使用mysql_config脚本。请参见Section 4.7.1, “mysql_config — Display Options for Compiling

    mysql_config显示编译或链接所需的选项:

    mysql_config --cflags
    mysql_config --libs

    您可以在命令行中使用反引号使用 mysql_config ,以包含它为特定选项生成的输出。例如,要编译和链接MySQL客户端程序,请使用 mysql_config ,如下所示:

    gcc -c `mysql_config --cflags` progname.c
    gcc -o progname progname.o `mysql_config --libs`

    详情请阅读mysql-config使用文档

    在Unix上,默认情况下链接使用动态库。要链接到静态客户端库,请将其路径名添加到link命令。例如,如果该库位于/usr/local/mysql/lib中,则像这样链接:

    gcc -o progname progname.o /usr/local/mysql/lib/libmysqlclient.a

    或使用mysql_config提供库的路径:

    gcc -o progname progname.o `mysql_config --variable=pkglibdir`/libmysqlclient.a

    mysql_config 当前不提供列出静态链接所需的所有库的方法,因此可能有必要在链接命令上命名其他库(例如,在Solaris上为-lnsl -lsocket)。要了解要添加哪些库,请使用 mysql_config --libsldd libmysqlclient.so(或macOS上的 otool -L libmysqlclient.dylib)。

    pkg-config可以代替mysql_config来获取信息,例如编译MySQL应用程序所需的编译器标志或链接库。例如,以下几对命令是等效的:

    mysql_config --cflags
    pkg-config --cflags mysqlclient
    
    mysql_config --libs
    pkg-config --libs mysqlclient

    关于 pkg-config 使用请自行百度,文档比较多。

    3、解决链接到MySQL客户端库的问题

    MySQL客户端库包括内置的SSL支持。在链接时无需指定-lssl或-lcrypto。这样做实际上可能导致运行时出现问题。

    如果链接器找不到MySQL客户端库,则对于以mysql_开头的符号,您可能会收到未定义的引用错误,例如以下所示:

    /tmp/ccFKsdPa.o: In function `main':
    /tmp/ccFKsdPa.o(.text+0xb): undefined reference to `mysql_init'
    /tmp/ccFKsdPa.o(.text+0x31): undefined reference to `mysql_real_connect'
    /tmp/ccFKsdPa.o(.text+0x69): undefined reference to `mysql_error'
    /tmp/ccFKsdPa.o(.text+0x9a): undefined reference to `mysql_close'

    您应该能够通过在链接命令的末尾添加 -Ldir_path -lmysqlclient 来解决此问题,其中 dir_path 表示客户端库所在目录的路径名。要确定正确的目录,请尝试以下命令:

    mysql_config --libs

    mysql_config 的输出可能指示在链接命令上也应指定其他库。您可以使用反引号将mysql_config输出直接包含在编译或链接命令中。例如:

    gcc -o progname progname.o `mysql_config --libs`

    如果在链接时发生错误,即未定义下限符号,请通过在编译/链接行的末尾添加-lm来链接至数学库。同样,如果对于系统上应该存在的其他功能(例如connect())出现未定义的引用错误,请查看手册页中所涉及的功能,以确定应将哪些库添加到链接命令中。

    如果对于系统中不存在的函数,出现诸如以下的未定义引用错误,则通常意味着您的MySQL客户端库是在与您的系统不100%兼容的系统上编译的:

    mf_format.o(.text+0x201): undefined reference to `__lxstat'

    在这种情况下,您应该下载最新版本的MySQL的源发行版,然后自己编译MySQL客户端库。请参见Section 2.9, “Installing MySQL from Source”.

    二、使用demo

    在Ubuntu16.04上:

    MySQL是直接使用apt-get安装的,默认版本为5.7.30,测试一下mysql_config:

    qb@qb-desktop:/usr$ mysql_config --cflags
    -I/usr/include/mysql 
    qb@qb-desktop:/usr$ mysql_config --libs
    -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -lrt -lssl -lcrypto -ldl
    qb@qb-desktop:/usr$ which mysql_config
    /usr/bin/mysql_config
    qb@qb-desktop:/usr$ mysql_config --version
    5.7.30
    qb@qb-desktop:/usr$

    注意:如果mysql_config不存在,按提示安装即可。

    在CentOS 7上:

    mysql_config不存在,yum也无法安装,这上面的MySQL是通过第三方rpm源安装的。搜索一下:发现没有头文件

    [root@jxh ~]# find / -name mysql_config
    [root@jxh ~]# whereis mysql
    mysql: /usr/bin/mysql /usr/lib64/mysql /usr/share/mysql /usr/share/man/man1/mysql.1.gz
    [root@jxh ~]# cd /usr/lib64/mysql/
    [root@jxh mysql]# ls
    libmysqlclient_r.so.18      libmysqlclient.so.18      libmysqlclient.so.20       mecab
    libmysqlclient_r.so.18.1.0  libmysqlclient.so.18.1.0  libmysqlclient.so.20.3.16  plugin

    发现只有动态库,按照 Centos下查看mysql的版本 查看版本为 5.7.29

    所以把Ubuntu上的头文件和库文件拷贝过来使用(我的开发环境搭载CentOS 7上)应该是可以的。

    在Ubuntu上 /usr/lib/x86_64-linux-gnu查看mysq库文件

    和CentOS 7上 5.7.29版本的基本一致,这里选择把 libmysqlclient.a静态库和/usr/include/mysql下的头文件都拷过去。

    然后参照以下文章进行调用,测试通过

    [1] VS2017项目中使用代码连接MySQL数据库,以及进行数据添加

    [2] C++实现对MySQL数据库的连接,以及增删改查

    Makefile文件如下:

    PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
    
    # PROJECT_ROOT = /root/eclipse-workspace/mysql_c_demo/
    
    # 中间文件, $(PROJECT_ROOT)*.o
    OBJS = mysql_c_demo.o MySQLManager.o
    
    # 目标文件名
    TARGET = mysql_c_demo
    
    # 编译器设置
    CXXFLAGS += -std=c++17 -flto
    
    # 头文件路径
    INCLUDE = -I$(PROJECT_ROOT)include/mysql
    
    # 链接库路径
    LDFLAGS = -L$(PROJECT_ROOT)lib
    
    # 链接库名
    LIBS = -lmysqlclient -lpthread -lz -lm -lrt -lssl -lcrypto -ldl
    
    # 指定运行时的动态库文件路径
    #RPATH = -Wl,-rpath=../lib
    
    # 宏定义
    # DEFS = -NO_USE_SSL
    
    # debug or release设置
    ifeq ($(BUILD_MODE),debug)
        CXXFLAGS += -g
    else ifeq ($(BUILD_MODE),run)
        CXXFLAGS += -O3
    else
        $(error Build mode $(BUILD_MODE) not supported by this Makefile)
    endif
    
    
    all:    $(TARGET)
    
    # 此处 $@ 表示目标文件集,即iot_servers, $^表示目标依赖集,即$(OBJS)
    mysql_c_demo:    $(OBJS)
        $(CXX) -o $@ $^ $(LDFLAGS) $(LIBS) $(RPATH)
    
    # %.o表 示所有以.o结尾的文件,%.cpp 表示所有以.cpp结尾的文件
    #  $@ 表示目标集,也就是*.o文件,$<  表示所有的依赖目标集,即*.c文件(见Makefile自动化变量部分)
    %.o:    $(PROJECT_ROOT)%.cpp
        $(CXX) -c $(CXXFLAGS) $(INCLUDE) -o $@ $<
    
    .PHONY: clean
    clean:
        rm -fr mysql_c_demo $(OBJS)

    该文件为eclipse项目生成,其中有些变量在普通环境下不存在,删掉或写成自己的路径即可。

    三、问题

    C API 默认使用 openssl 1.0版本,而我的项目中其他库必须依赖openssl 1.1版本,导致无法链接进去(TMD),所以又改用  Connector/C++。

    四、 Connector/C++

    如下是使用JDBC API的例子

    参考:

    官方文档

    MySql Connector/C++8简介

    使用Connector/C++操作MySQL

    MySQL connector/C++

    #include <mysql/jdbc.h>
    #include <iostream>
    
    using namespace std;
    
    int main(int argc, char **argv) {
    
        // 驱动
        sql::mysql::MySQL_Driver *driver = nullptr;
        // 连接
        sql::Connection *con = nullptr;
        // 数据库操作执行对象
        sql::Statement *state = nullptr;
        // 结果对象
        sql::ResultSet *result = nullptr;
    
        // 初始化驱动
        driver = sql::mysql::get_mysql_driver_instance();
        if (driver == nullptr)
        {
            cout << "driver is null" << endl;
        }
        // 建立连接
        con = driver->connect("tcp://127.0.0.1:3306", "root", "JiXiaohua@5712");
        if (con == NULL)
        {
            cout << "conn is null" << endl;
            return -1;
        }
        cout << "connect suceess" << endl;
    
        // 创建数据库操作执行对象
        state = con->createStatement();
        // use database
        state->execute("use c_mysql_test");
    
        // 执行查询
        // 查询
        result = state->executeQuery("select * from u_test where 1=1");
    
        // 输出查询
        cout << "id" << "		" << "name" << "		" << "age" << "		" << "comment" << endl;
        while(result->next())
        {
            int id = result->getInt("id");
            string name = result->getString("name");
            int age = result->getInt("age");
            string comment = result->getString("comment");
            cout << id << "		" << name << "		" << age << "		" << comment << endl;
        }
    
        // 释放对象
        delete state;
        delete con;
    
    
        return 0;
    }

    完全的Java jdbc风格。

    JDBC API的依赖库太大了,官方文档说了还可以使用X DevAPI and X DevAPI for C。

  • 相关阅读:
    jquery选择器
    jquery是方便了javascript,算是其子,导入方式必须记住,js文件自己官网下载
    checkbox操作全选、反选、取消
    onsubmit事件、事件传播判定函数stoppropagetion、事件使用2种方式
    onload函数绑定,byclass数组遍历、this获取整个标签内容
    区分byid和byclass的取值方法关键是有无数组、onfocus和onblur
    dom :document、element,如何取父标签和子标签,innertext获取标签内容
    定时器,setInterval、clearInterval
    一个简单css+js的开关组件
    Bootstrap 模态框强化
  • 原文地址:https://www.cnblogs.com/jixiaohua/p/12846625.html
Copyright © 2011-2022 走看看