一、数据类型
- 
MYSQLMYSQL是MYSQL数据库连接的句柄(handle),几乎所有的MYSQL函数都需使用该
 数据结构,不要尝试去复制该数据结构,因为不能保证副本是可用的。
- 
MYSQL_RESMYSQL_RES是SQL查询结果(result of query)。
- 
MYSQL_ROWMYSQL_ROW代表着一行数据,它被实现可数字节的字符串(an array of counted
 byte strings),但是认为它是以null为终结符的字符串,因为它可能包含二进制
 数据。一行数据通常通过mysql_fetch_row()来获取。
- 
MYSQL_FIELDMYSQL_FIELD包含元数据metadata,字段的信息(例如字段名,数据类型,大小等)
 通常可以通过重复使用mysql_fetch_field逐个获取字段,但字段值不包括在这个结构
 中,而是包含在MYSQL_ROW.
 MYSQL_FIELD的数据成员,当使用在不同场合,它的数据成员有不同含义:char* name:char* org_name:char* table:char* org_name:char* db:char* catlog:char* def:unsigned long length:unsigned long max_length:unsigned int name_length:unsigned int org_name_length:unsigned int table_length:unsigned int org_table_length:unsigned int db_length:unsigned int catlog_length:unsinged int def_length:unsigned int decimals:unsigned int charsetnr:enum enum_field_types type:unsigned int flags: flag以位形式体现字段属性,可以使用&配合以下FLAGS检查
 字段属性。FLAGS 说明 NOT_NULL_FLAG 字段不能为null PRI_KEY_FLAG 字段是primary key的一部分 UNIQUE_KEY_FLAG 字段是unique key的一部分 MULTIPLE_KEY_FLAG 字段是nonunique key的一部分 UNSIGNED_FLAG 字段有unsigned 属性 ZEROFILL_FLAG 字段有zerofill属性 BINARY_FLAG 字段有binary属性 AUTO_INCREMENT_FLAG 字段有auto_increment属性 ENUM_FLAG 字段是enum SET_FLAG 字段是set BLOB_FLAG 字段是blob TIMESTAMP_FLAG 字段是timestamp NUM_FLAG 字段是numeric NO_DEFAULT_VALUE_FLAG 字段没有默认值 通常的用法是 if(field->type & NOT_NULL_FLAG)
- 
MYSQL_FIELD_OFFSETMYSQL_FIELD_OFFSET代表着一个字段的偏移量,使用mysql_field_seek
- 
my_ulonglong
 数值类型,包括从0到1.84e19。
- 
my_bool
 布尔类型
二、API
| 函数名 | 说明 | 
|---|---|
| my_init() | 初始化一个全局变量和线程句柄 | 
| mysql_affected_rows() | 返回通过上次update、delete、insert改变、删除、插入的行数 | 
| mysql_autocommit() | 切换(toggle)自动提交模式(on/off) | 
| mysql_change_user() | 在一个打开的数据库连接中切换用户 | 
| mysql_character_set_name() | 返回当前连接的默认字符集名 | 
| mysql_client_find_plugin() | 返回一个plugin的指针 | 
| mysql_close() | 关闭一个服务器连接 | 
| mysql_commit() | 提交事务(transaction) | 
| mysql_connect() | 连接到一个服务器 | 
| mysql_create_db() | 创建一个数据库 | 
| mysql_date_seek() | |
| mysql_debug() | |
| mysql_drop_db() | 删除一个数据库 | 
| mysql_dump_debug_info() | 中止服务器写debug信息到log | 
| mysql_eof() | |
| mysql_errno() | 返回最近调用的mysql函数的error number | 
| mysql_error() | 返回醉经调用的mysql函数的error message | 
| mysql_escape_string | |
| mysql_fetch_field() | 返回下一个表字段的类型 | 
| mysql_fetch_field_direct() | |
| mysql_fetch_fields() | 返回一个所有字段的数组 | 
| mysql_fetch_lengths() | 返回当前行的所有列的长度 | 
| mysql_fetch_row() | 从结果集获取下一行 | 
| mysql_field_count() | |
| mysql_field_seek() | 移动游标(cursor)到特定行 | 
| mysql_field_tell() | 返回字段游标的位置 | 
| mysql_free_result() | 释放结果集的内存 | 
| mysql_get_character_set_info() | 返回默认字符集信息 | 
| mysql_get_client_info() | 返回客户版本信息 | 
| mysql_get_client_version() | 返回客户版本信息 | 
| mysql_get_host_info() | 返回数据库连接的描述信息 | 
| mysql_get_option() | |
| mysql_get_proto_info() | 返回连接的协议版本 | 
| mysql_get_server_info() | 返回服务版本信息 | 
| mysql_get_server_version() | 返回服务器版本信息 | 
| mysql_get_ssl_cipher() | 返回当前SSL cipher | 
| mysql_hex_string() | 编码字符串位十六进制模式 | 
| mysql_info() | 返回最近执行的query信息 | 
| mysql_init() | 得到并初始化一个MYSQL结构 | 
| mysql_insert_id() | 返回上次插入时自动生成的id | 
| mysql_kill() | 杀死一个线程 | 
| mysql_libary_end() | 结束mysql C API库 | 
| mysql_libary_init() | 初始化mysql C API 库 | 
| mysql_list_db() | 返回匹配正则表达式的数据库名 | 
| mysql_list_fields() | 返回匹配正则表达式的字段名 | 
| mysql_list_processes() | 返回当前服务线程 | 
| mysql_list_tables() | 返回匹配正则表达式的表名 | 
| mysql_load_plugin() | 加载一个plugin | 
| mysql_load_plugin_v() | 加载一个plugin | 
| mysql_more_results() | 检查是否有剩余的结果集 | 
| myssql_next_results() | 返回下一个在multiple-result 的结果集 | 
| mysql_num_fields() | 返回结果集中的列数 | 
| mysql_num_rows() | 返回结果集中的行数 | 
| mysql_options() | 设置mysql_real_connect()连接选项 | 
| mysql_ping() | 检查连接是否工作,并适当重连 | 
| mysql_query() | 执行一个SQL query | 
| mysql_real_connect() | 连接MYSQL Server | 
| mysql_real_query() | 执行一个SQL query | 
| mysql_reload() | |
| MySQL_refresh() | |
| mysql_reset_connection() | 重置连接去清除会话状态 | 
| mysql_rollback() | 回滚事务 | 
| mysql_row_seek() | 移动结果集中一个行偏移量 | 
| mysql_row_tell() | 返回行游标位置 | 
| mysql_select_db() | 选择一个数据库 | 
| mysql_server_end() | 结束mysql C API 库 | 
| mysql_server_init() | 初始化mysql C API 库 | 
| mysql_session_track_get_first() | |
| mysql_session_track_get_next() | |
| mysql_set_character_set() | 设置字符集 | 
| mysql_set_local_infile_default() | |
| mysql_set_local_infile_handler() | |
| mysql_set_server_option() | |
| mysql_sqlstate() | |
| mysql_shutdown() | 关闭sql服务器 | 
| mysql_ssl_set() | |
| mysql_stat() | |
| mysql_store_result() | |
| mysql_thread_end() | 结束线程handler | 
| mysql_thread_id() | 返回当前线程id | 
| mysql_thread_init() | 结束线程handler | 
| mysql_thread_safe() | 返回1如果客户端是完全的线程安全 | 
| mysql_user_result() | |
| mysql_waiting_count() | 返回上一次SQL statemennt的警告计数 | 
三、常用API详解
- my_init();
#include<my_global.h> #include<my_sys.h> void my_init(void); my_init()函数初始化一些使用MysQL必需的全局变量,而且它调用了mysql_thread_init()。 在使用MySQL客户端库之前调用my_init()是必要的,my_init()会被mysql_init(), mysql_library_init(),mysql_server_init(),mysql_connect()自动调用。如果你 能确保在调用其他MySQL函数之前调用以上的函数,那么可以不必显式调用my_init().
- mysql_init();
MYSQL* mysql_init(MYSQL* mysql); 返回值:一个已初始化的MYSQL句柄,如果没有足够内存返回NULL mysql_init()分配并初始化适用于mysql_real_connect()一个MYSQL对象,如果mysql参数 是一个空指针,那么函数内分配、初始化、并返回一个新的对象。否则,这个对象被初始化 并且返回对象的地址。如果mysql_init()在函数内分配了一个新的对象,它在关闭连接(即 调用mysql_close())时被释放。 在一个非多线程的环境中,mysql_init()会自动调用mysql_library_init(),但是要注 意的时mysql_library_init()在多线程环境中不是一个线程安全函数,所以mysql_init 也不是一个线程安全函数, 调用mysql_init(),无论是调用mysql_library之前切换线程,还是使用mutex保护 mysql_library_inti(),都必须在调用其他client libary call之前做完。
- 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 client_flag);
  mysql_real_connect()尝试去建立一条到MYSQL数据库的连接,在调用其他的API 函数之
  前mysql_real_connect()必须完全成功。  
  返回值:成功返回与mysql一样的MYSQL句柄,否则返回NULL
  
  参数:
  mysql: mysql必须是一个合法的MYSQL* 结构,调用mysql_init()可以初始化该结构,调
  用mysql_options()可以修改连接选项。  
  host: host必须是一个主机名或者一个IP地址。当host为NULL或者localhost时,意为连
  接到本地数据库。  
  user: user时用户登陆数据库的ID,如果user为NULL或者“",假定为当前用户。
  passwd: passwd为用户登陆数据库的密码  
  db: 数据库名,如果db不为NULL,连接到db的值默认的数据库  
  port: 如果port不为0,默认使用TCP/IP连接的端口号,port决定了数据库连接的类型  
  unix_socket: 如果unix_socket不为NULL,那么使用这个字符串指定的socket或者命名
  管道。  
  client_flag: 通常为0,但可以使用以下flag的组合来确定特定的特性。  
  CAN_HANDLE_EXPRIED_PASSWORDS:客户端能处理失效密码。 
  CLIENT_COMPRESS:使用压缩的tcp/ip协议。  
  CLIENT_FOUND_ROWS:返回找到的/匹配的行数,而不是返回改变的行数。  
  CLIENT_IGNORE_SIGPIPE:
  CLIENT_IGNORE_SPACE:允许在函数名后有空格。
  CLIENT_INTERACTIVE: 
  CLIENT_LOCAL_FILES: 
  CLIENT_MULTI_RESULT:
  CLIENT_MULTI_STATEMENT:
  CLIENT_ODBC:
  CLIENT_SSL:
  CLIENT_REMBER_OPTIONS:
  如果程序使用`CALL`statement来执行存储过程,那么CLIENT_MULITI_RESULTS必须被使
  用,因为每个CALL返回一个结果(result)来表明call status,另外还有执行存储过程返
  回的结果。 由于CALL可以返回多结果,程序中使用循环调用mysql_next_result()来检测
  是否还有结果。  
  MySQL5.7 中CLIENT_MULITI_RESULTS是默认使用的。  
  错误: 
  CR_CONN_HOST_ERROR:无法连接到MYSQL服务器
  CR_CONNECTION_ERROR:无法连接到本地MYSQL服务器
  CR_IPSOCK_ERROR:无法创建IPsocket
  CR_OUT_OF_MEMORY:内存溢出
  CR_SOCKET_CREATE_ERROR:无法创建unix连接  
  CR_UNKNOW_HOST:无法通过主机名解析ip地址  
  CR_VERSION_ERROR:
  CR_NAMEDPIPEOPEN_ERROR:
  CR_NAMEDPIPEWAIT_ERROR:
  CR_NAMEDPIPESTATE_ERROR:
  CR_SERVER_LOST:
  CR_ALREADY_CONNECTED:
- mysql_query();
int mysql_query(MYSQL* mysql,const char* stmt_str); 返回值:成功返回0,出错返会非0 执行一条以null为终结符的字符串指向的SQL Statement。通常,这个字符串是一条没有 分号或者\g结尾的单条SQL Statement。如果使用了multiple-statement,那么这个字符 串包含以分号或者\g分隔的多条SQL Statement。 mysql_query()不能使用包含二进制数据(binary data)的statement(二进制数据中可 能存在'\0'),如果想要使用带有二进制数据的statement,则使用mysql_real_query替代 如果想要知道statement是否有结果集,可以使用mysql_field_count()来检查。
- mysql_use_result();
MYSQL_RES* mysql_use_result(MYSQL* mysql); 返回值:成功时返回一个MYSQL_RES结构句柄,出错返回NULL 在调用mysql_query()或者mysql_real_query()之后,必须使用mysql_store_result() 或者mysql_use_result()为处理使用select、show、descrice、explanin、 check_table的statement返回的结果。在之后,还必须使用mysql_free_result()释放 result的空间。 mysql_use_result启动一个结果集检索(result set retrival)而不是像 mysql_store_result()读取整个结果集。相反,需要逐个调用mysql_fetch_row()来读取 每行数据。这个读取时直接从服务端读取而没有保存进一个临时的表或者本地缓存,它比 mysql_store_result()执行速度更快而且使用的内存更少。这个客户端仅为当前行分配内 存,并且这个communication buffer最多为max_allowed_packet字节。 当你使用mysql_use_result(),你必须执行mysql_fetch_row()知道返回NULL为止,否则 那些未被fetched的行将作为下一个query的结果集的一部分。 在mysql_use_result()完成之前,你不能在mysql_user_result()返回的resultset上使 用mysql_data_seek(),mysql_row_seek(),mysql_row_tell(),mysql_num_rows()或者 mysql_affected_rows,也不能执行其他的query。
- mysql_more_result()、mysql_next_result()
my_bool mysql_more_results(MYSQL *mysql); 检查是否有更多结果集 int mysql_next_result(MYSQL *mysql); 返回值: 0,执行成功,还有结果集 -1,执行成功,没有剩余结果集 >0,执行出错
- mysql_fetch_row();
MYSQL_ROW mysql_fetch_row(MYSQL_RES* result); mysql_fetch_row()取回结果集中的下一行。 返回值: 当在mysql_store_result()之后使用,mysql_fetch_row返回NULL意味着没有剩余行数据 当在mysql_use_result()之后使用,musql_fetch_row返回NULL意味着没有剩余行数据或 者和有错误发生。 行中值的数量(即列数)可由mysql_num_fields(results)确定 字段值的长度(the length of the field values in the row)可有 mysql_fetch_lengths()获取,空字段(empty field)或者字段值为NULL的长度都为0. 可以通过检查字段值的指针为NULL确定,否则为空字段。
- mysql_fetch_field()、mysql_fetch_lengths()
MYSQL_FIELD* mysql_fetch_field(MYSQL_RES* result); 循环调用mysql_fetch_field直到返回NULL获取结果集一行所有的field。 unsigned long* mysql_fetch_lengths(MYSQL_RES* result); 返回结果集中当前行中每一列的长度。
- mysql_field_count(),mysql_num_fields()
unsigned int mysql_field_count(MYSQL* mysql); 返回值: 返回上一次query statement中列数 unsigned int mysql_num_fields(MYSQL_RES* result); 返回值:返回结果集中的列数
- mysql_num_rows(),mysql_afftected_rows()
my_ulonglong mysql_num_rows(MYSQL_RES* result); 返回值:返回结果集中的行数 当使用mysql_store_result()时,mysql_num_rows()立即返回。 当使用mysql_use_result()时,mysql_num_rows()不会立即返回,而是在所有行都被抽 取后返回。 my_ulonglong mysql_affected_rows(MYSQL *mysql); 返回值:立即返回执行query statement后改变、删除、或插入的行的数量
- mysql_error()、mysql_errno()
const char *mysql_error(MYSQL *mysql); 返回错误的描述信息的字符串,如果没有错误发生返回空字符串 unsigned int mysql_errno(MYSQL *mysql); 返回上个mysql_xxx函数的错误码,如果为0则没有错误发生。
- mysql_commit()、mysql_autocommit()
my_bool mysql_commit(MYSQL *mysql); 提交当前事务 返回值:成功返回0,出错返回非0 my_bool mysql_autocommit(MYSQL *mysql, my_bool mode); 当mode为1,设置自动提交模式为打开,mode为0,关闭自动提交模式。 返回值:成功返回0,出错返回非0
- mysql_rollback()
my_bool mysql_rollback(MYSQL *mysql); 回滚当前事务 返回值:成功返回0,出错返回非0
- mysql_close()
void mysql_close(MYSQL *mysql); 关闭数据库连接
三、Statement的数据结构和API
- 
MYSQL_STMT
 这个数据结构是一个prepared statement的句柄,由函数mysql_stmt_init()
 创建,当不在使用时需使用函数mysql_stmt_close()关闭。不要尝试去复制一
 个MYSQL_STMT结构,因为无法保证它的副本能够被使用。
- 
MYSQL_BINDMYSQL_BIND既能用于向statement传入参数,也能接收statement的结果。
 对于输入参数,使用mysql_stmt_bind_param去结合(bind)参数。并使用函数mysql_stmt_execute()去执行。
 对于输出参数,使用mysql_stmt_bind_result去接收结果,并使用函数mysql_stmt_fetch()获取每行。MYSQL_BIND结构包含以下数据成员,对于有些数据成员,它的用法取决于它是
 输入还是输出参数。
| 数据成员 | 说明 | 
|---|---|
| enum enum_field_type buffer_type | 说明MYSQL_BIND的buffer数据成员的类型 | 
| void* buffer | buffer是一个void*指针,但作为输入参数时,它指向参数,但作为输出,它指向容纳行字段的空间 | 
| unsigned long buffer_length | buffer_length说明了buffer的实际大小 | 
| unsigned long* length | length是一个unsinged long指针,它说明buffer实际使用的空间大小。当作为输出参数,它表示statement返回行里某个字段的实际大小 | 
| my_bool* is_boll | is_boll是一个my_boll指针,如果值为NULL,他为true,否则为false,对于输入参数,设置is_null为true意味着你传递了一个NULL值作为statement参数,对于输出,如果is_null为true还是false是根据返回的某列的值是否为NULL | 
| my_bool is_unsigned | |
| my_error *error | 
- 
MYSQL_TIME
 这个数据结构直接用于发送和接收DATE,TIME,DATETIME,和TIMESTAMP数据类型。数据成员 说明 unsigned int year 年份 unsigned int mouth 月份 unsigned int day 日 unsigned int hour 小时 unsigned int minute 小时 unsigned int second 秒 my_bool neg 一个指明时间是否为负的flag unsigned long second_part 微秒部分 
对应的数据类型
MYSQL_BIND的buffer_type数据成员指明了statment参数和结果集列的数据类型,对
于输入参数,buffer_type指明了发送给服务器的参数的数据类型,对于输出 , buffer_type指明了从服务器接收的变量的数据类型。
buffer_type可以指定的输入类型有:
| 输入变量类型 | buffer_type 值 | SQL TYPE of Destination Value | 
|---|---|---|
| signed char | MYSQL_TYPE_TINY | TINYINT | 
| short int | MYSQL_TYPE_SHORT | SMALLINT | 
| int | MYSQL_TYPE_LONG | INT | 
| float | MYSQL_TYPE_FLOAT | FLOAT | 
| double | MYSQL_TYPE_DOUBLE | DOUBLE | 
| MYSQL_TIME | MYSQL_TYPE_TIME | TIME | 
| MYSQL_TIME | MYSQL_TYPE_DATE | DATE | 
| MYSQL_TIME | MYSQL_TYPE_DATETIME | DATETIME | 
| MYSQL_TIME | MYSQL_TYPE_TIMESTAMP | TIMESTAMP | 
| char [] | MYSQL_TYPE_STRING | TEXT,CHAR,VARCHAR | 
| char [] | MYSQL_TYPE_BLOG | BLOG,BINARY,VARBINARY | 
| MYSQL_TYPE_NULL | NULL | 
对于字符串数据,使用MYSQL_STRING 还是 MYSQL_BLOD取决于数据的值是字符还是
二进制字符串。
buffer_type可以指定的输出类型有:
| SQL TYPE OF RECEIVED VALUE | buffer_type value | output variable type | 
|---|---|---|
| TINYINT | MYSQL_TYPE_TINY | signed char | 
| SMALLINT | MYSQL_TYPE_SHORT | short int | 
| MEDIUMINT | MYSQL_TYPE_INT24 | int | 
| INT | MYSQL_TYPE_INT | int | 
| BIGINT | MYSQL_TYPE_LONG | long long int | 
| FLOAT | MYSQL_TYPE_FLOAT | float | 
| DOUBLE | MYSQL_TYPE_DOUBLE | double | 
| DECIMAL | MYSQL_TYPE_NEWDECIMAL | char[] | 
| YEAR | MYSQL_TYPE_TIME | short int | 
| TIME | MYSQL_TYPE_TIME | MYSQL_TIME | 
| DATE | MYSQL_TYPE_DATE | MYSQL_TIME | 
| DATETIME | MYSQL_TYPE_DATETIME | MYSQL_TIME | 
| TIMESTAMP | MYSQL_TYPE_TIMESTAMP | MYSQL_TIME | 
| CHAR,BINARY | MYSQL_TYPE_STRING | char [] | 
| CARCHAR,VARBINARY | MYSQL_TYPE_VAR_STRING | char [] | 
| TINYBLOB,TINYTEXT | MYSQL_TYPE_TINY_BLOB | char [] | 
| BLOD,TEXT | MYSQL_TYPE_VAR_BLOB | char [] | 
| MEDIUMBLOB,MEDIUMTEXT | MYSQL_TYPE_MEDIUM_BLOB | char [] | 
| LONGBLOB,LONGTEXT | MYSQL_TYPE_LONG_BLOB | char [] | 
| BIT | MYSQL_TYPE_BIT | char [] | 
| 函数名 | 说明 | 
|---|---|
| mysql_stmt_affected_rows() | 返回执行update、delete、insert后更新、删除、或插入的行数 | 
| mysql_stmt_attr_get() | 得到prepared statement的属性值 | 
| mysql_stmt_attr_set() | 设置prepared statement的属性值 | 
| mysql_stmt_bind_param() | 结合一个prepared statement的参数 | 
| mysql_stmt_close() | 释放prepared statement的空间 | 
| mysql_stmt_bind_result() | 结合一个prepared statement的结果集列 | 
| mysql_stmt_data_seek() | 寻找结果集中的任意行 | 
| mysql_stmt_errno() | 返回上次statement执行的错误码 | 
| mysql_stmt_error() | 返回上次statement执行的错误信息 | 
| mysql_fetch() | 抽取结果集中下一行的数据 | 
| mysql_stmt_fetch_column() | 抽取结果集中当前行的一列数据 | 
| mysql_stmt_field_count() | |
| mysql_stmt_free_result() | 释放statement句柄空间 | 
| mysql_stmt_init() | 分配并初始化一个MYSQL_STMT结构 | 
| mysql_stmt_insert_id() | 返回preparaed statement中auto_increment列生成的id | 
| mysql_stmt_next_result() | 返回下一个结果 | 
| mysql_stmt_num_rows() | 返回statement结果集中的行数 | 
| mysql_stmt_param_metadata() | |
| mysql_stmt_prepare() | 准备执行的SQL statement | 
| mysql_stmt_reset() | 重置一个statement | 
| mysql_stmt_result_metadata() | |
| mysql_stmt_row_seek() | |
| mysql_stmt_row_tell() | |
| mysql_stmt_send_long_data() | 发送一个大的数据 | 
| mysql_stmt_sqlstate() | 返回上次statement执行的SQLSTATE error code | 
| mysql_stmt_store_result() | 
使用步骤:
- 
使用 mysql_stmt_init()创建一个prepared statement句柄,然后调用mysql_stmt_prepare()去生成一个statement.
- 
如果statement会产生一个结果集,调用 mysql_stmt_result_metadat()
 去获取结果集的metadata。这个metadata是一个结果集的构成,它指明了query
 返回的结果集每列的信息。
- 
调用 mysql_stmt_bind_param去设置参数,所有参数都必须被设置,否则,
 statement的执行将返回一个错误或者未预期的结果集。
- 
调用 mysql_stmt_execute()去执行statement。
- 
如果statement产生了结果集,调用 mysql_stmt_bind_result()去获取结果集
 行数据。
- 
重复调用 mysql_stmt_fetch()去buffers一行行的抽取数据。
    当调用mysql_stmt_prepare()时,MYSQL服务器执行以下行为:
- 
服务器解析statementing并返回OK状态给客户端(通过分配一个statement id), 
 如果有结果集,服务器也将发送全部参数格式,列数,和结果集的metadata。所有
 的语法和语义都在服务器上检查。
- 
客户端将使用这个statement ID执行其他操作。 
 
- 
    当调用mysql_stmt_execut(),MYSQL服务器、客户端将执行以下操作:
- 
客户端将使用statement句柄并发送参数数据给服务器。 
- 
当服务器通过statement id辨别statement,他将使用提供的参数提到占位符,如果 
 statement产生了一个结果集,服务器将发送数据给客户端,否则,他将发送
 OK status 和插入、更新、删除的行数。
 
- 
   当调用mysql_stmt_fetch()时,MYSQL服务器、客户端将执行以下操作:
当客户端从结果集中当前行读取数据到buffers,并作必要的转换。
   如果发生了一个错误,可以通过调用mysql_stmt_errno(),mysql_stmt_error()   mysql_stmt_sqlstate()去获取错误号、错误信息、SQL状态。
来源:https://www.cnblogs.com/along4396/p/11993735.html