mysql的C API函数简介

翻译自:https://dev.mysql.com/doc/refman/5.7/en/c-api-function-overview.html

应用程序使用MySQL有如下几个步骤:

  1. 通过调用 mysql_library_init()来初始化MySQL库。这个函数同时存在于libmysqlclient 客户端库和libmysqld服务器端库,因此当你建立一个正常的客户端程序时要链接-libmysqlclient,或者建立一个服务器应用程序时,要链接 -libmysqld。
  2. 通过调用 mysql_init()来初始化一个连接句柄。通过调用mysql_real_connect()来连接服务器。
  3. 使用SQL语句操作数据库,并处理这些结果(下面这些讲具体讨论)。
  4. 通过调用mysql_close()来关闭MySQL服务器的连接。
  5. 通过调用 mysql_library_end()来终止使用MySQL库。

调用 mysql_library_init()和mysql_library_end()的目的是对MySQL合适的初始化与终止化。对于涉及客户端库的应用,他们提供改进的内存管理。如果你不调用mysql_library_end(),那么之前申请的一块内存将会一直存在(这个并不会增加应用程序内存的使用量,但是有些内存泄露检测器会检测到)。对于服务器端的程序,这两个函数可以开始和结束服务器端数据库。

在一个非多线程的环境中,调用mysql_library_init()可能可以省略,因为 mysql_init()将在必要的时候自动调用它。然而mysql_library_init()在多线程环境中并不是安全的,mysql_init()自动调用mysql_library_init()时也同样不安全。因此,要么你在增加任何线程之前调用mysql_library_init(),要么使用mutex来保护这个调用(不管是直接调用mysql_library_init()还是间接通过调用mysql_init()调用)。这个步骤必须在任何其他客户端库调用之前完成。

为了连接服务器端数据库,调用mysql_init()来初始化一个连接句柄,然后调用 mysql_real_connect()(需要有其他信息,比如host名字,用户名,密码等)。 mysql_real_connect()会将重连接标志位(reconnect flag )(MYSQL结构体中一部分)置为1(API版本5.0.3之前)或者置为0(API版本5.0.3之后)。这个标志位为1时,表明如果失去连接导致数据库查询或者操作语句不能执行,将在放弃前尝试重新连接。你可以使用 mysql_options()中的MYSQL_OPT_RECONNECT选项来控制重连接行为。最后,当数据库操作全部完成后,调用mysql_close()来关闭它。

当连接数据库成功后,客户端可以使用 mysql_query()或者mysql_real_query()发送SQL操作语句给服务器。这两个函数的区别是mysql_query()期望查询是一个 null-terminated string(以’\0’结尾的字符串),而mysql_real_query()则期望是一个counted string。如果字符串包含二进制数据(其中可能包含NULL字节),那么你必须使用mysql_real_query()。

对于每个非选择( non-SELECT )的查询(比如,INSERT,UPDATE,DELETE),你可以通过调用mysql_affected_rows()来发现多少行被改变。

对于SELECT查询,你可以以result集合检索被选择的行(注意,一些类似于SELECT的语句,包括SHOW,DESCRIBE和EXPLAIN,其实跟SELECT语句一样的)。

对于客户端来说,有两个方式来处理result集合。其中一个方式是通过调用 mysql_store_result()来一次性获得整个查询结果。整个函数从服务器数据库中获得所有的行,并保存在客户端中。第二个方式是通过调用mysql_use_result()来初始化一行一行的读取检索结果。这个函数只进行初始化,实际上并不会从服务器中获取任何的一行。

在上面两个情况下,你可以通过调用 mysql_fetch_row()来获取每一行。使用mysql_store_result()时,mysql_fetch_row()函数获取每一行,其中数据之前就已经从服务器数据库中获得;使用mysql_use_result()时,mysql_fetch_row()函数实际上是从服务器数据库中实时获取每一行。可以调用mysql_fetch_lengths()来获取每一行数据的大小信息。
当你操作完result集合后,调用 mysql_free_result()来释放之前使用的内存。

上面两个检索机制是互补的。可以根据客户端程序的具体应用来选择使用哪种方法。实际上,客户端更常使用mysql_store_result()。
mysql_store_result()的其中一个优点是,因为所有的行已经从数据库中获取,因此你不仅可以顺序的获取每一行,还可以使用 mysql_data_seek()或者mysql_row_seek()来改变当前在result集合中读取的位置(行号)。你也可以通过调用 mysql_num_rows()来获知有多少行。另一方面,mysql_store_result()对内存的要求可能会很高(对于很大的result集合来说),因此,你会更大概率上遇到内存不够用的情况。
mysql_use_result()的一个优点是客户端只需要很少的内存空间来存放result集合,因为每次只需要存一行的数据(因为申请的内存空间少了,mysql_use_result()运行速度也更快了)。缺点是你必须快速处理每一行来避免过多占用服务器数据库,而且你也不能在result集合中随机访问每一行,你只能顺序的访问每一行。全部的总行数你是不知道的,直到全部检索完毕。还有,你必须全部检索完所有行,即使当你在中间部分已经找到了想要的结果。

API函数在不需要知道是否是一个SELECT语句的情况下,提供了客户端对操作语句的一个合适的响应。你可以在调用每个mysql_query() (或者 mysql_real_query())函数之后,再调用 mysql_store_result()。如果result集合调用成功,这个操作语句是一个SELECT语句,然后就可以读取每一行。如果返回结果为失败,那么调用 mysql_field_count() 来查看失败结果是否是实际所期待的(你想得到的结果就是失败)。如果mysql_field_count()返回0,操作语句不返回任何数据(说明操作语句是一个INSERT,UPDATE或者DELETE语句等等),因此也不会返回行数据。如果mysql_field_count()返回非零值,那么操作语句本应该返回数据,实际却没有返回。这个表明是一个SELECT操作语句,但是操作失败了。可以去mysql_field_count()查看如何处理这种情况。
mysql_store_result() 和 mysql_use_result() 都可以让你获取有关result集合的字段信息(字段的序号,名称和类型等)。你可以通过重复调用 mysql_fetch_field()来顺序的获取信息,或者调用 mysql_fetch_field_direct()(该函数需要给定序号)来获取某一序号的信息(不需要按顺序获取)。可以通过调用mysql_field_seek()来改变当前字段光标位置。也可以通过调用mysql_fetch_fields()一次性获取全部字段。
对于检测和报告错误,MySQL提供了获取用户信息的渠道,即使用 mysql_errno() 和 mysql_error() 两个函数。这两个函数为最新调用的函数提供了返回错误代号或者错误信息,可以让你知道错误什么时候发生和错误是什么。

举例:
服务器上数据库表单如下:
这里写图片描述
示例代码如下:

#include<iostream>  
#include<string>  
#include<mysql.h> 
#include <iomanip>

using namespace std;

int main()
{
    //必备数据结构  
    MYSQL mydata;  //=mysql_init((MYSQL*)0); 
    if (NULL != mysql_init(&mydata)) 
        cout << "mysql_init()succeed" << endl;
    else {
        cout << "mysql_init()failed" << endl;
        return -1;
    }

    //初始化数据库  
    if (0 == mysql_library_init(0, NULL, NULL)) 
        cout << "mysql_library_init()succeed" << endl;  
    else {
        cout << "mysql_library_init()failed" << endl;
        return -1;
    }
    //连接数据库   //这里的地址,用户名,密码,数据库,端口可以根据自己本地的情况更改  
    if (NULL != mysql_real_connect(&mydata, "192.168.110.218", "root", "123456", "test", 3306, NULL, 0))    
    {
        cout << "mysql_real_connect()succeed" << endl;
    }
    else
    {
        cout << "mysql_real_connect()failed" << endl;
        return -1;
    }

    //MYSQL myCont;
    MYSQL_RES *result;
    MYSQL_ROW sql_row;
    int res;
    //mysql_query(&mydata, "SET NAMES GBK"); //设置编码格式
    res = mysql_query(&mydata, "select * from fruits");//查询
    if (!res)
    {
        result = mysql_store_result(&mydata);
    //  result = mysql_use_result(&mydata);//使用这句的时候,必须使用mysql_fetch_row读完全部的行,直到为NULL
        if (result)
        {
            unsigned int num_fields = mysql_num_fields(result);
            cout << "num_fields: " << num_fields << endl;

            MYSQL_FIELD *field;
        //  mysql_field_seek(result, 1);
            while ((field = mysql_fetch_field(result)))
            {
                cout << setiosflags(ios::left)<< setw(15) << field->name;
            }
            cout << endl;
            //mysql_data_seek(result, 2);           
            while (sql_row = mysql_fetch_row(result))//获取具体的数据
            {       
                for (int i = 0; i < mysql_num_fields(result); i++)
                {
                    if (sql_row[i])
                        cout << setiosflags(ios::left)<< setw(15) << sql_row[i];
                //  else cout << "               ";
                }
                cout << endl;           
            }
        }
        mysql_free_result(result);
    }
    else
    {
        cout << "query sql failed!" << endl;
    }

    //操作……  
    mysql_close(&mydata);
    mysql_library_end();
    cout << "end..." << endl;
    getchar();
    return 0;
}

程序运行结果如下:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/hjl240/article/details/75578004