文章目录
C_API(简单的)
# MYSQL C_API
结构体
- MYSQL 数据库连接的类型,代表一个mysql连接
- MYSQL_RES 查询返回的结果集,返回的多条数据构成的内存结构 不仅包含返回的二维的字符串数组 还有一些元数据信息
- MYSQL_ROW 一行记录,字符串数组, row[0],...row[n-1]
- MYSQL_ROWS 由 MYSQL_ROW 构成的链表
函数
- mysql_init 初始化数据库连接,并没有建立连接
1.传NULL,会自动分配地址,初始化之后返回
2.如果有指针对象,返回的还是原来的地址
- mysql_close 释放数据库连接
- mysql_error 显示错误信息,字符串显示
- mysql_real_connect 建立数据库连接,TCP套接字
- mysql_query 执行最简单的sql语句;insert update DELETE select
- mysql_store_result 加载结果集,查询语句之后使用,使用缓存在内存中会存储一份
- mysql_use_result 加载select结果集
- mysql_free_result 释放结果集
- mysql_num_rows 结果集中的元数据:行数
- mysql_num_fields 结果集中的元数据:列数
- mysql_fetch_row 从结果集获得一行数据
- mysql_insert_id 获得插入记录自动生成的id
用户发送请求,程序通过端口监听用户的,程序中会包含一系列的操作来访问数据库,但是mysql官方为我们封装好了一系列的函数,我们可以通过函数来对mysql服务器进行访问,获得结果,对数据进行一系列的处理,然后返回给用户。
安装这个库
locate mysql.h
locate libmysqlclient.so
只包含头文件但是主要的代码在动态库中,所以在编译的时候要将动态库进行链接。
使用流程
可以类比mysql自带客户端
# 给mysql的服务器的监听端口,发送信息,建立连接,
mysql -u root -p123456
# 操作完成会进入mysql的客户端,就可以给服务器发送sql语句对数据进行操作。
初始化连接
mysql_init
建立连接
mysql_real_connect
执行SQL语句
mysql_query
当一个连接,建立好之后可以查询多次。
处理结果
mysql_store_result
适用于数据量较小的情况。会在内存申请空间。在内存中存储一份。
注意:经验又是没有返回结果也不会返回null,所以最好拿到返回结果之后做一下判断,如果是null,就是没有返回数据,如果不是null,使用mysql_num_rows()函数,判断是不是0,如果不是0,就进行常规的后续操作。
msyql_use_result
mysql_num_rows
msyql_free_result
mysql_num_fields
mysql_fetch_row
获取一行数据的信息
拿到的数据库的存储形式:
多线程安全
假如同一个进程中,有多个线程,如果我多个线程用来访问一个静态资源不会出现问题,但是现在我要没有线程与mysql服务器都建立一个连接,然后他们都进行访问同一动态资源,都调用mysql_init()函数,虽然unbantu说这个事线程安全函数(也就是说这个函数在设计的时候有加锁)但是并不是这样的,同时调用mysql_init函数可能会出现两个线程拿到的是同一个连接,然后用于查询的时候返回数据,接收数据的时候会出现数据读取错误,但是我们不对mysql_init(),这个函数就行加锁操作,我们不能对库函数进行修改,但是我们可以自己封装一个函数,这个函数的主要作用就是加锁,执行库函数,然后解锁操作,来保证多线程的安全。
关闭连接
mysql_close()
检验API是否出错
mysql_error
#include <mysql/mysql.h>
#include <stdio.h>
int main(void)
{
//初始化连接
MYSQL *mysql = mysql_init(NULL);
//mysql 返回值要接收 就是初始化好的结构体指针
// MYSQL *mysql = NULL;
// mysql = mysql_init(mysql);
//使用库中的检验错误的函数 mysql_error
printf("%s\n", mysql_error(mysql));
// 建立到mysql服务器的连接 并且发送账号密码
mysql_real_connect(mysql, "localhost", "root", "123456", "test_connect", 0, NULL, 0);
printf("%s\n", mysql_error(mysql));
//上面连接已经建立,账号密码已经验证 -> 发送sql语句给mysql服务器
// mysql_query(mysql, "insert into class values(NULL, 3)");
//删除数据
mysql_query(mysql, "delete from class where id=6");
//使用完成只之后要关闭连接
mysql_close(mysql);
return 0;
}
mysql> select * from class;
+----+------------+
| id | class_name |
+----+------------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+----+------------+
3 rows in set (0.01 sec)
#include <mysql/mysql.h>
#include <stdio.h>
int main(void)
{
//初始化连接
MYSQL *mysql = mysql_init(NULL);
//mysql 返回值要接收 就是初始化好的结构体指针
// MYSQL *mysql = NULL;
// mysql = mysql_init(mysql);
//使用库中的检验错误的函数 mysql_error
printf("%s\n", mysql_error(mysql));
// 建立到mysql服务器的连接 并且发送账号密码
mysql_real_connect(mysql, "localhost", "root", "123456", "test_connect", 0, NULL, 0);
printf("%s\n", mysql_error(mysql));
//只要是执行select sql语句,必须接收返回值,并且释放
//因为如果不接收返回值,下一次接收可能会接收到上一次的数据,导致数据错乱
//发送sql语句
mysql_query(mysql, "select * from class");
//通过mysql_store_result()函数获取mysql_query的返回值
MYSQL_RES * res = mysql_store_result(mysql);
//加返回值的验证
if(mysql_num_rows(res) != 0)
{
//对数据进行处理
MYSQL_ROW row;
//从结果集中拿出一行,如果结果集中没有更多数据或结果集为空,则返回NULL
while((row = mysql_fetch_row(res)))
{
unsigned int colunm;
colunm = mysql_num_fields(res);
for(int i = 0; i < colunm; i++)
{
printf("%s ", row[i]);
}
printf("\n");
}
}
mysql_free_result(res);
//使用完成只之后要关闭连接
mysql_close(mysql);
return 0;
}
mysql> select * from class;
+----+------------+
| id | class_name |
+----+------------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 3 |
| 5 | 3 |
+----+------------+
5 rows in set (0.00 sec)