Mysql_API

MySql数据库API编程

初始化

初始化函数原型:MYSQL *mysql_init(MYSQL *mysql)

处理错误码的函数:unsigned int mysql_errno(MYSQL *mysql)

#include <stdio.h>
#include <stdlib.h>
#include "mysql.h"

int main()
{
	//MYSQL *mysql_init(MYSQL *mysql) 
	MYSQL *mysql = mysql_init(NULL);
	if(mysql==NULL){
		printf("mysql init error\n");
		return -1;
	}
	printf("mysql init ok\n");

	return 0;
}

使用ldd命令可以查看该可执行文件运行所依赖的库文件。

编译:makefile 管理

src = $(wildcard *.c)
target = $(patsubst %.c, %, $(src))
inc_path = /usr/include/mysql/
lib_path = /usr/lib64/mysql/
all: $(target)
%:%.c
	gcc $< -o $@ -I$(inc_path) -L$(lib_path) -lmysqlclient -lstdc++ -lpthread -ldl -lrt
clean:
	-rm -rf $(target)
.PHONY: all clean

连接数据库、关闭数据库

连接数据库函数原型: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 client_flag)

关闭数据库函数原型:void mysql_close(MYSQL *mysql)

#include <stdio.h>
#include <stdlib.h>
#include "mysql.h"

int main()
{
	//初始化
	//MYSQL *mysql_init(MYSQL *mysql) 
	MYSQL *mysql = mysql_init(NULL);
	if(mysql==NULL){
		printf("mysql init error\n");
		return -1;
	}
	printf("mysql init ok\n");

	//连接mysql数据库
	//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 client_flag) 
	MYSQL *conn = mysql_real_connect(mysql, "192.168.10.145", "root", "123456", "scott", 0, NULL, 0);
	if(conn==NULL){
		printf("mysql_real_connect error,[%s]\n", mysql_error(mysql));
		return -1;
	}
	printf("connect mysql OK, [%p], [%p]\n", mysql, conn);

	//关闭数据库连接
	mysql_close(conn);
	
	return 0;
}

查询表数据

mysql_query函数不单单能完成查询sql的功能,还能完成非select语句在c程序中的执行。

并且该函数本身直接支持静态SQL。查询以\0结尾的字符串。

如果语句中包含二进制数据,则需要调用mysql_real_query来执行查询语句。

注意: mysql_query执行的SQL语句不应为语句添加终结分号(‘;’)或“\g”。

函数原型:int mysql_query(MYSQL *mysql, const char *query); 成功返回0,失败返回非0

//mysql执行sql语句
#include <stdio.h>
#include <stdlib.h>
#include "mysql.h"

int main()
{
	//初始化
	//MYSQL *mysql_init(MYSQL *mysql) 
	MYSQL *mysql = mysql_init(NULL);
	if(mysql==NULL){
		printf("mysql init error\n");
		return -1;
	}
	printf("mysql init ok\n");

	//连接mysql数据库
	//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 client_flag) 
	MYSQL *conn = mysql_real_connect(mysql, "192.168.10.145", "root", "123456", "scott", 0, NULL, 0);
	if(conn==NULL){
		printf("mysql_real_connect error,[%s]\n", mysql_error(mysql));
		return -1;
	}
	printf("connect mysql OK, [%p], [%p]\n", mysql, conn);

	//执行sql语句
	//int mysql_query(MYSQL *mysql, const char *query) 
	char sSQL[255] = "insert into mytest values(1, 'xiaohuang')";
	int ret = mysql_query(conn, sSQL);
	if(ret!=0){
		printf("mysql_query error, [%s]\n", mysql_error(mysql));
	}
	printf("mysql_query ok\n");

	//关闭数据库连接
	mysql_close(conn);
	
	return 0;
}

获取结果集

一种方式是通过mysql_store_result()将整个结果集全部取回来。

另一种方式调用mysql_use_result()初始化获取操作,但暂时不取回任何记录。视结果集的条目数选择获取结果集的函数。

两种方法均通过mysql_fetch_row()来访问每一条记录。

函数原型:MYSQL_RES *mysql_store_result(MYSQL *mysql)

成功返回MYSQL_RES结果集指针,失败返回NULL。

MYSQL_RES是一个结构体类型,可以从mysql.h头文件中找到该结构体的定义

MYSQL_RES *result = mysql_store_result(mysql);
if (result == NULL) {
	ret = mysql_errno(mysql);
	printf("mysql_store_result error: %s\n", mysql_error(mysql));
	return ret;	
}

该函数调用成功,则SQL查询的结果被保存在result中,但我们不清楚有多少条数据。所以应使用游标的方式将结果集中的数据逐条取出。

解析结果集

通过游标一行一行fetch结果集中的数据。根据游标使用的一般特性,应使用循环结构,到达结尾或者出错,返回NULL。

函数原型:MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)

char **mysql_fetch_row(){
    char **tmp = (char **) malloc(sizeof(char *) * 8);
    for (i = 0; i < 8; i++) {
        tmp[i] = (char *)malloc(50);
    }
    strcpy(tmp[0], "7369");
    strcpy(tmp[1], "SMITH");
    strcpy(tmp[2], "CLERK");
    ...
    return tmp;
}

成功返回下一行的MYSQL_ROW结构。

如果没有更多要检索的行或出现了错误,返回NULL

select * from emp 可以看到emp表一共有8列数据。循环将每行上每一列的数据显示到屏幕。

	MYSQL_ROW row = NULL;				//typedef char **MYSQL_ROW;	
	while ((row = mysql_fetch_row(result))) {
	printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", row[0],row[1],row[2],row[3],row[4],row[5],row[6],row[7]);
	}

MYSQL_ROW的本质是 typedef char ** MYSQL_ROW;

释放结果集

结果集处理完成,应调用对应的函数释放所占用的内存。

函数原型:void mysql_free_result(MYSQL_RES *result);

成功释放参数传递的结果集。没有失败情况。

mysql_free_result(result);

获取列数

函数原型:

unsigned int mysql_field_count(MYSQL *mysql) 从mysql句柄中获取有多少列。

unsigned int mysql_num_fields(MYSQL_RES *result) 从返回的结果集中获取有多少列。

int num = mysql_field_count(connect); 
while (row = mysql_fetch_row(result)) {
    for (i = 0; i < num; i++) {
        printf("%s\t", row[i]);
    }
    printf("\n");
    //printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", row[0],row[1],row[2],row[3],row[4],row[5],row[6],row[7]);
}

获取表头

MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result) ; 全部获取

MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result) ; 获取单个

MYSQL_FIELD也是一个结构体类型,其内部保存了选择列表项的信息,其中的name成员变量就保存着列名。可从头文件mysql.h中找到其定义:

MYSQL_FIELD *fields = NULL;
fields = mysql_fetch_fields(result);	//得到表头的结构体数组
for (i = 0; i < num; i++) {		//已通过 mysql_field_count	获取了总列数	
    printf("%s\t", fields[i].name);	//每一列的列名保存在name成员中 
}
printf("\n");

测试示例

#include <stdio.h>
#include <stdlib.h>
#include "mysql.h"

int main(){
	//初始化
	//MYSQL *mysql_init(MYSQL *mysql) 
	MYSQL *mysql = mysql_init(NULL);
	if(mysql==NULL){
		printf("mysql init error\n");
		return -1;
	}
	printf("mysql init ok\n");

	//连接mysql数据库
	//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 client_flag) 
	MYSQL *conn = mysql_real_connect(mysql, "192.168.10.145", "root", "123456", "scott", 0, NULL, 0);
	if(conn==NULL){
		printf("mysql_real_connect error,[%s]\n", mysql_error(mysql));
		return -1;
	}
	printf("connect mysql OK, [%p], [%p]\n", mysql, conn);

	//执行sql语句
	//int mysql_query(MYSQL *mysql, const char *query) 
	char sSQL[255] = "select * from mytest";
	int ret = mysql_query(conn, sSQL);
	if(ret!=0){
		printf("mysql_query error, [%s]\n", mysql_error(mysql));
	}
	printf("mysql_query ok\n");

	//获取结果集
	//MYSQL_RES *mysql_store_result(MYSQL *mysql) 
	MYSQL_RES *results = mysql_store_result(conn);
	if(results==NULL)
	{
		printf("mysql_store_result error,[%s]\n", mysql_error(mysql));
		return -1;
	}
	printf("mysql_store_result ok\n");


	int i = 0;
	//获取列数
	//	unsigned int mysql_num_fields(MYSQL_RES *result) 
	unsigned int num = mysql_num_fields(results);

	//获取表头信息---列名
	//MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)
	MYSQL_FIELD *fields = mysql_fetch_fields(results);
	if(fields==NULL)
	{
		printf("mysql_fetch_fields error,[%s]\n", mysql_error(mysql));
		return -1;
	}
	//打印表头信息
	printf("+------+-----------+\n");
	for(i=0; i<num; i++)
	{
		printf("%s\t", fields[i].name);
	}
	printf("\n");
	printf("+------+-----------+\n");
	
	//获取结果集中每一行记录
	MYSQL_ROW row;
	while((row=mysql_fetch_row(results)))
	{
		for(i=0; i<num; i++)
		{
			printf("%s\t", row[i]);	
		}
		printf("\n");
	}
	printf("+------+-----------+\n");

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

	//关闭数据库连接
	mysql_close(conn);
	
	return 0;
}

MySql 客户端工具实现

MySQL基础类API函数,可以编写程序实现简单的sqlplus/mysql工具的功能。

  1. 仿照mysql工具,应在连接数据库成功之后,在一个while循环中不断的接受用户输入的SQL语句。定义char sqlbuf[1024]存储用户输入的SQL语句。初始化该buf,并提示用户输入SQL语句。使用gets函数在循环中动态接收用户输入。

    while (1) {
        memset(sqlbuf, 0, sizeof(sqlbuf));
        printf("\nYourSQL> ");
        fgets(sqlbuf, sizeof(sqlbuf), stdin);
    }
    
  2. mysql_query(connect, sqlbuf)之前,如果用户输入了exit那么程序直接结束。

  3. 在执行完 mysql_query(connect, sqlbuf)之后,应该判别用户输入的是否为select语句。如不是select语句不需要查询结果集、处理结果集等繁复操作。

  4. 如用户输入的是有结果集的SQL语句,将获取列数、获取结果集、获取表头、解析结果集、释放结果集等相关代码一起并入if (strncmp(sqlbuf, "select", 6))中。

  5. 中文问题:修改mysql_real_connect()参数,连接到表中有中文数据的数据库,如mydb2,执行程序,测试显示中文出现乱码。我们可以使用mysql_query函数来解决该问题。

    while (1) 之前使用 ret = mysql_query(mysql, "set names utf8");来设置查询属性(也可以加到while中)。表示在查询的时候使用utf8的形式进行查询。

    或者获取当前使用的字符集:

    const char *mysql_character_set_name(MYSQL *mysql)

    mysql_set_character_set(mysql, "utf8");

//模拟mysql客户端程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "mysql.h"

int main()
{
    int ret = 0;
	//mysql初始化---mysql_init
	MYSQL *mysql = mysql_init(NULL);
	if(mysql==NULL){
        ret = mysql_error(mysql);
		printf("mysql_init error:%d\n", ret);
		return -1;
	}
    printf("init ok...\n");
	
	//连接数据库
	MYSQL *conn = mysql_real_connect(mysql, "localhost", "root", "123456", "scott", 0, NULL, 0);
	if(conn==NULL){
		printf("connect mysql db error, [%s]\n", mysql_error(mysql));
		return -1;
	}
    printf("connect ok...\n");
	
	//获取当前进程使用的字符集
	printf("before:[%s]\n", mysql_character_set_name(conn));
	
	//设置字符集为utf8格式
	mysql_set_character_set(conn, "utf8");
	printf("after:[%s]\n", mysql_character_set_name(conn));

	int i;
	int n;
	int ret;
	int num;
	char *p;
	char buf[1024];
	MYSQL_RES *results;
	MYSQL_FIELD *fields;
	MYSQL_ROW row;
	
	//进入循环等待用户输入sql语句并执行sql语句
	while(1){
		//打印提示符
		write(STDOUT_FILENO, "mysql> ", strlen("mysql> "));
		
		//读取用户输入
		memset(buf, 0x00, sizeof(buf));
		read(STDIN_FILENO, buf, sizeof(buf));
		
		//1-去掉末尾的;
		p = strrchr(buf, ';');
		if(p!=NULL){
			*p = '\0';
		}
		
		//2-去掉回车
		if(buf[0]=='\n') {
			continue;
		}
		
		//去掉最前面的几个空格
		for(i=0; i<strlen(buf); i++){
			if(buf[i]!=' ')
			{
				break;
			}
		}
		n = strlen(buf);
		memmove(buf, buf+i, n-i+1); //+1表示多拷贝一个\0
		printf("[%s]\n", buf);
		
		//若输入的是退出: exit EXIT quit QUIT
		if(strncasecmp(buf, "exit", 4)==0 || strncasecmp(buf, "quit", 4)==0){
			mysql_close(conn);
			exit(0);
		}
		
		//执行sql语句
		ret = mysql_query(conn, buf);
		if(ret!=0){
			printf("%s\n", mysql_error(conn));
			continue;
		}
		
		//若用户输入的不是select查询
		if(strncasecmp(buf, "select", 6)!=0){
			printf("Query OK, %ld row affected\n", mysql_affected_rows(conn));
			continue;
		}
		
		//下面是select查询的情况	
		//获取结果集
		results = mysql_store_result(conn);
		if(results==NULL){
			printf("%s\n", mysql_error(conn));
			continue;
		}
		
		//获取列数
		num = mysql_num_fields(results);
		
		//获取表头---列名
		fields = mysql_fetch_fields(results);
		if(fields==NULL){
			printf("%s\n", mysql_error(conn));
			mysql_free_result(results);
			continue;
		}
		//打印表头
		printf("+----------+-----------+\n");
		for(i=0; i<num; i++){
			printf("%s\t", fields[i].name);
		}
		printf("\n");
		printf("+----------+-----------+\n");
		
		//循环获取每一行记录
		while(row=mysql_fetch_row(results)){
			for(i=0; i<num; i++)
			{
				printf("%s\t", row[i]);
			}
			printf("\n");
		}
		printf("+----------+-----------+\n");
		
		//释放结果集
		mysql_free_result(results);
	}
		
	//关闭数据库连接
	mysql_close(conn);
	
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值