美文网首页
Linux下C++和GCC实现MySQL中的SQL查询结果集导出

Linux下C++和GCC实现MySQL中的SQL查询结果集导出

作者: 久别重逢已经那边v发 | 来源:发表于2025-03-11 07:18 被阅读0次

在Linux中用C++和GCC在MySQL 8数据库里实现将SQL查询语句的结果集用LibXL库导出为Excel 2007格式的文件,并且针对每一列的数据调整到合适宽度,并封装为函数。

#include <mysql_connection.h>
#include <mysql_driver.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <libxl.h>
#include <vector>
#include <string>
#include <locale>
#include <codecvt>

using namespace std;
using namespace sql;
using namespace libxl;

// 字符串转宽字符串转换器
wstring string_to_wstring(const string& str) {
    wstring_convert<codecvt_utf8<wchar_t>> converter;
    return converter.from_bytes(str);
}

bool exportToExcel(const string& host, const string& user, const string& pass,
                  const string& db, int port, const string& query,
                  const string& filename) {
    
    sql::mysql::MySQL_Driver* driver = nullptr;
    sql::Connection* con = nullptr;
    sql::Statement* stmt = nullptr;
    sql::ResultSet* res = nullptr;
    Book* book = xlCreateXMLBook();
    
    if (!book) {
        cerr << "Failed to initialize Excel book" << endl;
        return false;
    }

    try {
        // 初始化数据库连接
        driver = sql::mysql::get_mysql_driver_instance();
        con = driver->connect("tcp://" + host + ":" + to_string(port), user, pass);
        con->setSchema(db);

        // 执行查询
        stmt = con->createStatement();
        res = stmt->executeQuery(query);
        
        // 获取元数据
        ResultSetMetaData* meta = res->getMetaData();
        int colCount = meta->getColumnCount();
        vector<int> colWidths(colCount, 0);

        // 创建Excel工作表
        Sheet* sheet = book->addSheet("Data");
        if (!sheet) {
            cerr << "Failed to create sheet" << endl;
            return false;
        }

        // 写入表头并计算初始宽度
        for (int i = 0; i < colCount; ++i) {
            wstring wcol = string_to_wstring(meta->getColumnLabel(i + 1));
            sheet->writeStr(0, i, wcol.c_str());
            colWidths[i] = static_cast<int>(wcol.length());
        }

        // 写入数据并跟踪最大列宽
        int row = 1;
        while (res->next()) {
            for (int i = 0; i < colCount; ++i) {
                string val = res->getString(i + 1);
                wstring wval = string_to_wstring(val);
                
                sheet->writeStr(row, i, wval.c_str());
                
                // 更新最大列宽
                if (wval.length() > colWidths[i]) {
                    colWidths[i] = static_cast<int>(wval.length());
                }
            }
            ++row;
        }

        // 设置列宽(包含10%的余量)
        for (int i = 0; i < colCount; ++i) {
            sheet->setCol(i, i, colWidths[i] * 1.1);
        }

        // 保存Excel文件
        if (!book->save(filename.c_str())) {
            cerr << "Error saving file: " << book->errorMessage() << endl;
            return false;
        }

    } catch (SQLException& e) {
        cerr << "MySQL Error: " << e.what() << endl;
        cerr << "Error code: " << e.getErrorCode() << endl;
        return false;
    } catch (const exception& e) {
        cerr << "General Error: " << e.what() << endl;
        return false;
    }

    // 清理资源
    delete res;
    delete stmt;
    delete con;
    book->release();

    return true;
}

使用示例:

int main() {
    bool result = exportToExcel(
        "localhost",   // MySQL主机
        "root",        // 用户名
        "password",    // 密码
        "testdb",      // 数据库名
        3306,         // 端口
        "SELECT * FROM products",  // 查询语句
        "output.xlsx"  // 输出文件名
    );

    if (result) {
        cout << "Export completed successfully" << endl;
    } else {
        cout << "Export failed" << endl;
    }

    return 0;
}

编译命令示例:

g++ -std=c++11 -o exporter exporter.cpp \
    -I/usr/local/include/mysql-cppconn-8 \
    -I/path/to/libxl/include \
    -L/usr/local/lib -lmysqlcppconn \
    -L/path/to/libxl/lib -lxl -Wl,-rpath,/path/to/libxl/lib

注意事项:

  1. 需要正确安装MySQL Connector/C++和LibXL库
  2. LibXL需要有效的授权许可证(试用版会在生成文件添加水印)
  3. 列宽计算基于字符数量,中文等宽字符可能需要调整系数
  4. 确保数据库连接参数正确且有足够权限
  5. 处理大数据量时需要适当的内存管理

这个实现:

  1. 封装为独立函数,参数包含所有必要配置
  2. 自动调整列宽并包含10%的余量
  3. 支持Unicode字符
  4. 包含基本错误处理
  5. 自动清理分配的资源
  6. 生成符合Excel 2007+标准的.xlsx文件

相关文章

网友评论

      本文标题:Linux下C++和GCC实现MySQL中的SQL查询结果集导出

      本文链接:https://www.haomeiwen.com/subject/rnuumjtx.html