文章目录
1.访问数据库
命令行式客户端向mysqld下达指令
网页版
图形化界面
语言级别的库/包
mysql的基础,我们之前已经学过,后面我们只关心使用。要使用C语言连接mysql,需要使用mysql官网提供的库,大家可以去官网下载。我们使用C接口库来进行连接。要正确使用,我们需要做一些准备工作:
- 保证mysql服务有效
- 在官网上下载合适自己平台的mysql connect库,以备后用。其中include 包含所有的方法声明,lib 包含所有的方法实现(打包成库)。
- 要使用库,必须先进行初始化!
- 初始化完毕之后,必须先链接数据库,在进行后续操作。(mysql网络部分是基于TCP/IP的)。第一个参数 MYSQL是 C api中一个非常重要的变量(mysql_init的返回值),里面内存非常丰富,有
port,dbname,charset等连接基本参数。它也包含了一个叫 st_mysql_methods的结构体变量,该变量
里面保存着很多函数指针,这些函数指针将会在数据库连接成功以后的各种数据操作中被调用。
mysql_real_connect函数中各参数,基本都是顾名思意。
MYSQL *mysql_real_connect(MYSQL *mysql, const char *host,
const char *user,
const char *passwd,
const char *db,
unsigned int port,
const char *unix_socket,
unsigned long clientflag);
- sql执行完以后,如果是查询语句,我们当然还要读取数据,如果update,insert等语句,那么就看下操
作成功与否即可。我们来看看如何获取查询结果: 如果mysql_query返回成功,那么我们就通过
mysql_store_result这个函数来读取结果。原型如下:MYSQL_RES *mysql_store_result(MYSQL *mysql);
- 该函数会调用MYSQL变量中的st_mysql_methods中的 read_rows 函数指针来获取查询的结果。同时该
函数会返回MYSQL_RES 这样一个变量,该变量主要用于保存查询的结果。同时该函数malloc了一片内
存空间来存储查询过来的数据,所以我们一定要记的 free(result),不然是肯定会造成内存泄漏的。 执行
完mysql_store_result以后,其实数据都已经在MYSQL_RES 变量中了,下面的api基本就是读取
MYSQL_RES 中的数据。
2.vscode-c-api客户端
方法一:重新安装相关数据
安装成功样例
方法二:直接使用之间安装mysql的附加数据
之前我们在安装mysql时 sudo yum install -y mysql-community-server 通过yum源安装mysql社区服务器 实际上他不止帮我们安装了服务器 还安装了客户端和各种开发包(devl)
理应你下载了mysql,就应该有上面的,如果没有:
sudo yum install -y mysql-devel
gcc/g++默认只会连接c/c++的库 要想链接系统中的其他库 /lib64/mysql or /usr/lib64/mysql 需要主动-l选项+库名(去前缀和后缀)且-L+库路径
如果编译报错 需要将上面的库加到系统库路径 使得在编译时 编译器能找到库【怎么加 看链接那一篇】
之前将动静态库时还要加-I选项 这里怎么不用?:我们的代码包含了<mysql/mysql.h>,编译时会去/usr/include找mysql/mysql.h, 如果写成<mysql.h> 则需要下面指令
查看mysql文档方式
使用c-mysql-api库访问mysqld
MySQL类型结构体
typedef struct st_mysql
{
NET net; /* Communication parameters */
unsigned char *connector_fd; /* ConnectorFd for SSL */
char *host,*user,*passwd,*unix_socket,*server_version,*host_info;
char *info, *db;
struct charset_info_st *charset;
MYSQL_FIELD *fields;
MEM_ROOT field_alloc;
my_ulonglong affected_rows;
my_ulonglong insert_id; /* id if insert on table with NEXTNR */
my_ulonglong extra_info; /* Not used */
unsigned long thread_id; /* Id for connection in server */
unsigned long packet_length;
unsigned int port;
unsigned long client_flag,server_capabilities;
unsigned int protocol_version;
unsigned int field_count;
unsigned int server_status;
unsigned int server_language;
unsigned int warning_count;
struct st_mysql_options options;
enum mysql_status status;
my_bool free_me; /* If free in mysql_close */
my_bool reconnect; /* set to 1 if automatic reconnect */
/* session-wide random string */
char scramble[SCRAMBLE_LENGTH+1];
my_bool unused1;
void *unused2, *unused3, *unused4, *unused5;
LIST *stmts; /* list of all statements */
const struct st_mysql_methods *methods;
void *thd;
/*
Points to boolean flag in MYSQL_RES or MYSQL_STMT. We set this flag
from mysql_stmt_close if close had to cancel result set of this object.
*/
my_bool *unbuffered_fetch_owner;
/* needed for embedded server - no net buffer to store the 'info' */
char *info_buffer;
void *extension;
} MYSQL;
mysql_real_connect 函数概述
mysql_real_connect 是 MySQL C API 中的一个重要函数,用于建立与 MySQL 数据库服务器的连接。它提供了丰富的参数以支持不同的连接方式和认证机制。
参数
MYSQL *mysql: 指向 MYSQL 结构的指针,该结构在调用 mysql_real_connect 之前应通过 mysql_init 或 mysql_init_character_set 初始化。
const char *host: 数据库服务器的地址。可以是主机名或IP地址。如果为 NULL 或 “localhost”,则尝试通过 UNIX 套接字连接(如果可用)。
const char *user: 连接数据库时使用的用户名。
const char *passwd: 用户的密码。如果为 NULL,则假定不使用密码。
const char *db: 要连接的数据库名。如果为 NULL,则先连接到 MySQL 服务器,稍后再选择数据库。
unsigned int port: MySQL 服务器的端口号。默认为 3306。
const char *unix_socket: UNIX 套接字的路径名(仅当 host 是 NULL 或 “localhost” 时使用)。如果为 NULL,则使用默认值。
unsigned long clientflag: 客户端标志的位或组合,用于修改 mysql_real_connect 的行为。例如,MYSQL_CLIENT_COMPRESS 启用压缩,MYSQL_CLIENT_SSL 启用 SSL 加密等。
返回值
如果连接成功,mysql_real_connect 返回 mysql 参数的指针(即传入的 MYSQL 结构指针)。
如果连接失败,返回 NULL。此时,可以使用 mysql_error(mysql) 函数获取错误信息。
函数功能
mysql_real_connect 函数的主要功能是尝试根据提供的参数建立与 MySQL 数据库服务器的连接。如果连接成功,它配置并返回 MYSQL 结构以供后续数据库操作使用。如果连接失败,它返回 NULL 并设置错误状态,以便通过 mysql_error 函数获取错误详情。
底层原理
在底层,mysql_real_connect 会执行以下步骤来建立连接:
解析参数:解析传入的参数,包括主机名、端口、用户名、密码等。
建立网络连接:根据提供的主机名和端口号(或 UNIX 套接字路径),使用 TCP/IP 或 UNIX 套接字建立与 MySQL 服务器的网络连接。
认证:向 MySQL 服务器发送认证请求,包括用户名和密码(如果提供)。MySQL 服务器会验证这些信息,并返回认证结果。
选择数据库(如果指定):如果提供了数据库名,则向 MySQL 服务器发送请求以选择该数据库。
配置会话:根据 clientflag 参数配置会话选项,如启用压缩、SSL 加密等。
返回结果:如果所有步骤都成功完成,则返回 MYSQL 结构指针以供后续使用;如果失败,则返回 NULL 并设置错误状态。
mysql_real_connect 是 MySQL C API 中建立数据库连接的核心函数,它提供了灵活的配置选项以支持不同的使用场景。
证明链接成功
query接口
mysql_query 函数是 MySQL C API 中的一个重要函数,用于在已经建立的数据库连接上执行 SQL 语句。这个函数接收两个参数:一个是指向 MYSQL 结构的指针(代表已经打开的数据库连接),另一个是包含要执行的 SQL 语句的字符串。
函数原型
c
int mysql_query(MYSQL *mysql, const char *q);
参数
MYSQL *mysql: 指向已经通过 mysql_real_connect 或其他类似函数成功建立的数据库连接的 MYSQL 结构体的指针。
const char *q: 一个以 null 结尾的字符串,包含了要执行的 SQL 语句。
返回值
如果 SQL 语句执行成功,mysql_query 返回 0。
如果执行失败,返回非 0 值。此时,可以通过 mysql_error(mysql) 函数获取详细的错误信息。
使用示例
c
#include <mysql.h>
#include <stdio.h>
int main() {
MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;
conn = mysql_init(NULL);
if (conn == NULL) {
fprintf(stderr, "%s\n", mysql_error(conn));
return 1;
}
if (mysql_real_connect(conn, "host", "user", "password", "database", 0, NULL, 0) == NULL) {
fprintf(stderr, "%s\n", mysql_error(conn));
mysql_close(conn);
return 1;
}
if (mysql_query(conn, "SELECT * FROM table_name")) {
fprintf(stderr, "%s\n", mysql_error(conn));
mysql_close(conn);
return 1;
}
res = mysql_use_result(conn);
while ((row = mysql_fetch_row(res)) != NULL) {
printf("%s\n", row[0]); // 假设第一列是字符串类型
}
mysql_free_result(res);
mysql_close(conn);
return 0;
}
注意事项
在调用 mysql_query 之前,必须确保已经通过 mysql_real_connect 或其他函数成功建立了数据库连接。
mysql_query 适用于执行任何 SQL 语句,包括查询(SELECT)、更新(UPDATE)、删除(DELETE)和插入(INSERT)等。
对于返回结果集的查询(如 SELECT),通常需要使用 mysql_use_result 或 mysql_store_result 来处理结果。
在处理完结果集后,应使用 mysql_free_result 释放结果集占用的资源。
始终检查 mysql_query 的返回值以确认 SQL 语句是否成功执行,并在出错时通过 mysql_error 获取错误信息。
在完成数据库操作后,应使用 mysql_close 关闭数据库连接以释放相关资源。
复习指针
#include <stdio.h>
void changePointer(int **ptr) {
*ptr = malloc(sizeof(int)); // 分配新的内存,并改变ptr指向的指针的指向
**ptr = 10; // 修改新分配的内存中的值
}
int main() {
int *p = NULL;
changePointer(&p); // 传递p的地址,即二级指针
printf("%d\n", *p); // 输出10
free(p); // 释放内存
return 0;
}
代码
#include <iostream>
#include <mysql/mysql.h>
// 端口错误或mysqld未启动都会导致连接失败
// ctrl+d:事务流结束 有些平台如windows是ctrl+c
// const std::string host ="localhost";
const std::string host = "127.0.0.1";
const std::string user = "lhr";
const std::string passwd = "lhr.547521";
const std::string db = "c_cpp_test";
const unsigned int port = 3306;
int main()
{
printf("mysql client Version: %s\n\n", mysql_get_client_info());
// 句柄:fd/file*/c++文件流对象
MYSQL *_mysql = mysql_init(nullptr);
if (nullptr == _mysql)
{
fprintf(stderr, "%s\n", mysql_error(_mysql));
return 1;
}
if (mysql_real_connect(_mysql, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
{
fprintf(stderr, "%s\n", mysql_error(_mysql));
mysql_close(_mysql);
return 1;
}
// 建立好链接之后 获取英文没有问题 获取中文是乱码
// 需要设置链接的默认字符集是utf8 客户端原始默认是latin1
// 而我们设置了mysqld的默认字符集是utf8 编码解码不一致!
mysql_set_character_set(_mysql, "utf8");
// std::string sql ="update user set name='jimmy' where id=2";
// std::string sql = "insert into user (name, age, phone) values('张三',19,'654321987687')";
// std::string sql="delete from user where id=1";
std::string sql = "select * from user";
// std::string sql="select name,age from user where id=1";
int value = mysql_query(_mysql, sql.c_str());
if (value == 0)
std::cout << "Query OK" << std::endl;
else
{
fprintf(stderr, "%s\n", mysql_error(_mysql));
mysql_close(_mysql);
return 1;
}
MYSQL_RES *res = mysql_store_result(_mysql);
if (nullptr == res)
{
fprintf(stderr, "%s\n", mysql_error(_mysql));
mysql_close(_mysql);
return 1;
}
my_ulonglong rows = mysql_num_rows(res);
unsigned int cols = mysql_num_fields(res);
MYSQL_FIELD *fields = mysql_fetch_fields(res);
std::cout << std::endl;
std::cout << "select database(): " << fields[0].db << std::endl;
std::cout << "select table(): " << fields[0].table << std::endl;
std::cout << std::endl;
for (int i = 0; i < cols; i++)
std::cout << fields[i].name << " ";
std::cout << std::endl;
///* return data as array of strings */
// typedef char **MYSQL_ROW;
MYSQL_ROW line;
for (int i = 0; i < rows; i++)
{
line = mysql_fetch_row(res);
for (int j = 0; j < cols; j++)
std::cout << line[j] << " ";
std::cout << std::endl;
}
/*
std::string sql;
while (true)
{
std::cout << "MySOL>>>";
if (!std::getline(std::cin, sql) || sql == "quit")
{
std::cout << "bye bye" << std::endl;
break;
}
int n = mysql_query(_mysql, sql.c_str());
if (n == 0)
std::cout << sql << "success:" << n << std::endl;
else
mysql_close(_mysql);
}
std::cout << "connect susccess" << std::endl;
*/
mysql_free_result(res);
mysql_close(_mysql);
return 0;
}
理解mysql_res
mysql将所有的数据,读取出来的时候全部都当做字符串
3.图形化界面
具体如何安装使用,网上有很多资料,这里不再赘述。