linux学习笔记(35)C语言连接mysql

C语言连接MySQL(详细教程)

1. 安装开发库

复制代码
# 切换到管理员
sudo su

# 安装MySQL开发库
apt install libmysqlclient-dev

# 验证安装
find /usr -name "mysql.h"

2. 核心API函数详解

连接流程需要的函数:
cpp 复制代码
// 1. 初始化连接句柄
MYSQL *mysql_init(MYSQL *mysql);

// 2. 连接数据库
MYSQL *mysql_real_connect(
    MYSQL *mysql,           // 连接句柄
    const char *host,       // 主机地址:"localhost"或"127.0.0.1"
    const char *user,       // 用户名:"root"
    const char *passwd,     // 密码:"你的密码"
    const char *db,         // 数据库名:"testdb"
    unsigned int port,      // 端口号:3306或0(默认)
    const char *unix_socket,// NULL
    unsigned long clientflag // 0
);

// 3. 执行SQL语句
int mysql_query(MYSQL *mysql, const char *query);

// 4. 获取结果集
MYSQL_RES *mysql_store_result(MYSQL *mysql);

// 5. 获取行数
uint64_t mysql_num_rows(MYSQL_RES *result);

// 6. 获取列数
unsigned int mysql_num_fields(MYSQL_RES *result);

// 7. 逐行读取数据
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

// 8. 释放结果集
void mysql_free_result(MYSQL_RES *result);

// 9. 关闭连接
void mysql_close(MYSQL *mysql);

// 10. 错误处理
const char *mysql_error(MYSQL *mysql);
unsigned int mysql_errno(MYSQL *mysql);

3. 完整示例代码(带详细注释)

示例1:查询数据
cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>

int main() {
    MYSQL mysql;          // 定义MySQL连接对象
    MYSQL_RES *res;       // 结果集指针
    MYSQL_ROW row;        // 行数据指针
    int fields;           // 字段数
    int rows;             // 行数
    
    // 1. 初始化连接句柄
    printf("1. 初始化MySQL连接...\n");
    if (mysql_init(&mysql) == NULL) {
        printf("初始化失败: %s\n", mysql_error(&mysql));
        return -1;
    }
    
    // 2. 连接数据库
    printf("2. 连接数据库...\n");
    if (mysql_real_connect(&mysql, "localhost", "root", "123456", "school", 0, NULL, 0) == NULL) {
        printf("连接失败: %s\n", mysql_error(&mysql));
        mysql_close(&mysql);
        return -1;
    }
    printf("连接成功!\n");
    
    // 3. 设置字符集(重要!避免中文乱码)
    printf("3. 设置字符集...\n");
    if (mysql_query(&mysql, "set names utf8") != 0) {
        printf("设置字符集失败: %s\n", mysql_error(&mysql));
    }
    
    // 4. 执行查询语句
    printf("4. 执行查询...\n");
    char *sql = "SELECT id, name, age, gender, score FROM students";
    if (mysql_query(&mysql, sql) != 0) {
        printf("查询失败: %s\n", mysql_error(&mysql));
        mysql_close(&mysql);
        return -1;
    }
    
    // 5. 获取结果集
    printf("5. 获取结果集...\n");
    res = mysql_store_result(&mysql);
    if (res == NULL) {
        printf("获取结果集失败: %s\n", mysql_error(&mysql));
        mysql_close(&mysql);
        return -1;
    }
    
    // 6. 获取行数和列数
    rows = mysql_num_rows(res);
    fields = mysql_num_fields(res);
    printf("查询结果: %d 行, %d 列\n\n", rows, fields);
    
    // 7. 打印表头
    MYSQL_FIELD *field;
    printf("| ID | 姓名 | 年龄 | 性别 | 成绩 |\n");
    printf("|----|------|------|------|------|\n");
    
    // 8. 逐行读取并打印数据
    while ((row = mysql_fetch_row(res)) != NULL) {
        // 注意:row[i] 可能为NULL,需要判断
        printf("| %s | %s | %s | %s | %s |\n",
               row[0] ? row[0] : "NULL",
               row[1] ? row[1] : "NULL", 
               row[2] ? row[2] : "NULL",
               row[3] ? row[3] : "NULL",
               row[4] ? row[4] : "NULL");
    }
    
    // 9. 释放资源
    printf("\n9. 释放资源...\n");
    mysql_free_result(res);
    mysql_close(&mysql);
    printf("程序结束!\n");
    
    return 0;
}
编译命令:

gcc -o mysql_query mysql_query.c -lmysqlclient

./mysql_query

示例2:插入数据
cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>

int main() {
    MYSQL mysql;
    
    // 初始化并连接数据库
    mysql_init(&mysql);
    if (!mysql_real_connect(&mysql, "localhost", "root", "123456", "school", 0, NULL, 0)) {
        printf("连接失败: %s\n", mysql_error(&mysql));
        return -1;
    }
    
    // 设置字符集
    mysql_query(&mysql, "set names utf8");
    
    // 准备插入数据的SQL语句
    char sql[256];
    char name[] = "新学生";
    int age = 19;
    char gender[] = "男";
    float score = 87.5;
    
    // 构造SQL语句(注意:字符串需要引号)
    sprintf(sql, "INSERT INTO students (name, age, gender, score) VALUES ('%s', %d, '%s', %.1f)",
            name, age, gender, score);
    
    printf("执行SQL: %s\n", sql);
    
    // 执行插入
    if (mysql_query(&mysql, sql) == 0) {
        printf("插入成功!影响行数: %lld\n", 
               (long long)mysql_affected_rows(&mysql));
    } else {
        printf("插入失败: %s\n", mysql_error(&mysql));
    }
    
    mysql_close(&mysql);
    return 0;
}
示例3:事务处理
cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <mysql/mysql.h>

// 转账函数:从from_id转amount金额到to_id
int transfer_money(MYSQL *mysql, int from_id, int to_id, double amount) {
    // 开始事务
    if (mysql_query(mysql, "START TRANSACTION") != 0) {
        printf("开始事务失败: %s\n", mysql_error(mysql));
        return -1;
    }
    
    // 扣款
    char sql1[256];
    sprintf(sql1, "UPDATE account SET balance = balance - %.2f WHERE id = %d", amount, from_id);
    if (mysql_query(mysql, sql1) != 0) {
        printf("扣款失败: %s\n", mysql_error(mysql));
        mysql_query(mysql, "ROLLBACK");
        return -1;
    }
    
    // 检查余额是否足够
    sprintf(sql1, "SELECT balance FROM account WHERE id = %d", from_id);
    mysql_query(mysql, sql1);
    MYSQL_RES *res = mysql_store_result(mysql);
    MYSQL_ROW row = mysql_fetch_row(res);
    double balance = atof(row[0]);
    mysql_free_result(res);
    
    if (balance < 0) {
        printf("余额不足!当前余额: %.2f\n", balance);
        mysql_query(mysql, "ROLLBACK");
        return -1;
    }
    
    // 收款
    char sql2[256];
    sprintf(sql2, "UPDATE account SET balance = balance + %.2f WHERE id = %d", amount, to_id);
    if (mysql_query(mysql, sql2) != 0) {
        printf("收款失败: %s\n", mysql_error(mysql));
        mysql_query(mysql, "ROLLBACK");
        return -1;
    }
    
    // 提交事务
    if (mysql_query(mysql, "COMMIT") == 0) {
        printf("转账成功!\n");
        return 0;
    } else {
        printf("提交事务失败: %s\n", mysql_error(mysql));
        mysql_query(mysql, "ROLLBACK");
        return -1;
    }
}

int main() {
    MYSQL mysql;
    
    mysql_init(&mysql);
    if (!mysql_real_connect(&mysql, "localhost", "root", "123456", "testdb", 0, NULL, 0)) {
        printf("连接失败: %s\n", mysql_error(&mysql));
        return -1;
    }
    
    // 创建测试表
    mysql_query(&mysql, "CREATE TABLE IF NOT EXISTS account ("
               "id INT PRIMARY KEY, "
               "name VARCHAR(50), "
               "balance DECIMAL(10,2))");
    
    // 插入测试数据
    mysql_query(&mysql, "INSERT INTO account VALUES (1, '张三', 1000.00)");
    mysql_query(&mysql, "INSERT INTO account VALUES (2, '李四', 500.00)");
    
    // 执行转账:张三给李四转200元
    transfer_money(&mysql, 1, 2, 200.00);
    
    mysql_close(&mysql);
    return 0;
}
相关推荐
smartpi_ai21 分钟前
51 单片机写好了,大模型语音怎么接?17T 全驱动的现成方案、双板串口分工的边界与画板前的三项硬件确认
单片机·嵌入式硬件·学习
Linux系统运维工程师_郭主任42 分钟前
运维人还在被拒offer?现在能考的,只有 RHCE 10.0。
linux
wujiuhsu1 小时前
图片里的简体中文怎么翻译成繁体?商品图、详情页和海报批量转换方法
经验分享·笔记
自养Agent1 小时前
MCP Server Boundary Audit Report
linux·服务器·人工智能·windows·大模型·llm
辣知1 小时前
辣知·化智82 人类文明演化规律文化传承
学习
Coisinier2 小时前
docker命令管理镜像及容器
linux·运维·nginx·docker·容器·操作系统
A心有千千结2 小时前
通过 SSH 反向代理让服务器借用本机网络访问 GitHub 的最佳实践
linux·服务器·网络·git·ssh·github
书生执笔画浮沉3 小时前
Linux 内核模块为什么不能自己解决兼容性问题?
linux·c·kernel·update·灵感
15Moonlight3 小时前
Linux网络(03):Socket 编程 TCP
linux·网络·tcp/ip
广州灵眸科技有限公司3 小时前
单芯片同时跑 Linux 与 RT-Thread:RV1126B的AMP异构方案完整拆解
linux·运维·服务器