mysql api c客户端

官网:https://dev.mysql.com/doc/refman/8.0/en/c-api.html

1 API介绍

1.1 初始化函数

MYSQL *mysql_init(MYSQL *mysql)

mysql 可以传 NULL
返回值: 分配的句柄 MYSQL*指针

1.2 设置连接选项

int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg)

描述
可用于设置额外的连接选项,并影响连接的行为。可多次调用该函数来设置数个选项。
应在mysql_init()之后、以及mysql_connect()或mysql_real_connect()之前调用mysql_options()。
选项参量指的是你打算设置的选项。Arg参量是选项的值。如果选项是整数,那么arg应指向整数的值。

范例

my_bool reconnect = true;
mysql_options(m_mysql, MYSQL_OPT_RECONNECT, &reconnect);
mysql_options(m_mysql, MYSQL_SET_CHARSET_NAME, "utf8mb4");

MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。好在utf8mb4是utf8的超集,除了将编码改为utf8mb4外不需要做其他转换。
要在 Mysql 中保存 4 字节长度的 UTF-8 字符,需要使用 utf8mb4 字符集,但只有 5.5.3 版本以后的才支持(查看版本: select version() ; )。我觉得,为了获取更好的兼容性,应该总是使用 utf8mb4 而非 utf8. 对于 CHAR 类型数据,utf8mb4 会多消耗一些空间,根据 Mysql 官方建议,使用 VARCHAR 替代 CHAR。

1.3 连接到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 初始化的句柄指针
  • host 主机地址
  • user 用户名 – mysql数据库 root
  • passwd 用户的密码
  • db 要连接的数据库
  • port 端口 一般填0,mysql默认端口 3306
  • unix_socket 本地套接字 ,一般填NULL
  • client_flag 连接标志 一般填0

返回值: 成功返回 连接句柄,失败返回 NULL

1.4 设定登陆的字符集 – 登陆之后

int mysql_set_character_set(MYSQL *mysql, char *csname)

参数:

  • mysql 连接句柄
  • csname 字符集的名称 utf8

1.5 query功能非常强大 增删改查都可以

int mysql_query(MYSQL *mysql, const char *query)

参数介绍:

  • mysql 连接句柄
  • query 执行的sql

反回值:

  • 成功 返回 0
  • 失败 返回 非0

1.6 获得结果集的函数

MYSQL_RES *mysql_store_result(MYSQL *mysql)

返回值:
如果读取结果集失败,mysql_store_result()还会返回Null指针。
通过检查mysql_error()是否返回非空字符串,mysql_errno()是否返回非0值,或mysql_field_count()是否返回0,可以检查是否出现了错误。

范例

MYSQL_RES* res = mysql_store_result(m_mysql);
if (!res) {
    log_error("mysql_store_result failed: %s", mysql_error(m_mysql));
    return NULL;
}

1.7 释放结果集

void mysql_free_result(MYSQL_RES *result)

范例:

if (m_res) {
    mysql_free_result(m_res);
    m_res = NULL;
}

1.8 获取查询的显示列的长度

unsigned int mysql_num_fields(MYSQL_RES *result)

描述: 返回结果集中的行数。
注意,你可以从指向 结果集的指针或指向连接句柄的指针获得行数 。如果mysql_store_result()或mysql_use_result()返回NULL,应使用连接句柄(因而没有结果集指针)。在该情况下,可调用mysql_field_count()来判断mysql_store_result()是否生成了非空结果。这样,客户端程序就能采取恰当的行动,而不需要知道查询是否是SELECT语句(或类似SELECT的语句)。在下面的示例中,介绍了执行该操作的方式。

范例

int num_fields = mysql_num_fields(m_res);
MYSQL_FIELD* fields = mysql_fetch_fields(m_res);

1.9 获取列信息

MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)

描述
返回采用MYSQL_FIELD结构的结果集的列。重复调用该函数,以检索关于结果集中所有列的信息。未剩余字段时,mysql_fetch_field()返回NULL。
每次执行新的SELECT查询时,将复位mysql_fetch_field(),以返回关于第1个字段的信息。调用mysql_field_seek()也会影响mysql_fetch_field()返回的字段。
如果调用了mysql_query()以在表上执行SELECT,但未调用mysql_store_result(),如果调用了mysql_fetch_field()以请求BLOB字段的长度,MySQL将返回默认的Blob长度(8KB)。之所以选择8KB是因为MySQL不知道BLOB的最大长度。应在日后使其成为可配置的。一旦检索了结果集,field->max_length将包含特定查询中该列的最大值的长度。

返回值
当前列的MYSQL_FIELD结构。如果未剩余任何列,返回NULL。

1.10 取出一行信息

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)

描述
检索结果集的下一行。在mysql_store_result()之后使用时,如果没有要检索的行,mysql_fetch_row()返回NULL。在mysql_use_result()之后使用时,如果没有要检索的行或出现了错误,mysql_fetch_row()返回NULL。
行内值的数目由mysql_num_fields(result)给出。如果行中保存了调用mysql_fetch_row()返回的值,将按照row[0]到row[mysql_num_fields(result)-1],访问这些值的指针。行中的NULL值由NULL指针指明。
可以通过调用mysql_fetch_lengths()来获得行中字段值的长度。对于空字段以及包含NULL的字段,长度为0。通过检查字段值的指针,能够区分它们。如果指针为NULL,字段为NULL,否则字段为空。

返回值
下一行的MYSQL_ROW结构。如果没有更多要检索的行或出现了错误,返回NULL。

1.11 显示受影响的行数

my_ulonglong mysql_affected_rows(MYSQL *mysql)

描述
返回上次UPDATE更改的行数,上次DELETE删除的行数,或上次INSERT语句插入的行数。对于UPDATE、DELETE或INSERT语句,可在mysql_query()后立刻调用。对于SELECT语句,mysql_affected_rows()的工作方式与mysql_num_rows()类似。

返回值
大于0的整数表明受影响或检索的行数。“0”表示UPDATE语句未更新记录,在查询中没有与WHERE匹配的行,或未执行查询。“-1”表示查询返回错误,或者,对于SELECT查询,在调用mysql_store_result()之前调用了mysql_affected_rows()。由于mysql_affected_rows()返回无符号值,通过比较返回值和“(my_ulonglong)-1”或等效的“(my_ulonglong)~0”,检查是否为“-1”。

/* gcc -o connect mysql.c -lmysqlclient -I/usr/include/mysql -L/usr/lib64/mysql/ */
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql.h>
#include <unistd.h>
#define _USER_      "root"          /* 用户名 */
#define _HOST_      "127.0.0.1"     /* host */
#define _PASSWD_    "123456"        /* root 用户名密码 */
#define _DB_        "teamtalk"         /* 库名 */
#define _PORT_      3306            /* port */
/* 打印信息   结果集 */
void show_information( MYSQL_RES * res, MYSQL *mysql )
{
    int     i;
    MYSQL_ROW   row;            /*  */
    /* unsigned long *lengths; */
    unsigned int    num_fields;
    MYSQL_FIELD *field;         /* 字段名 */
    /* 数据的长度unsigned int mysql_num_fields(MYSQL_RES *result) */
    num_fields = mysql_num_fields( res );
    /*
     * 返回列长unsigned long *mysql_fetch_lengths(MYSQL_RES *result)
     * lengths  = mysql_fetch_lengths(res);
     */
    printf( "num_fields = [%d]\n", num_fields );
    /* 字段名 */
    for ( i = 0; i < num_fields, field = mysql_fetch_field( res ); i++ )
    {
        printf( " %s\t", field->name );
    }
    printf( "\n" );
    printf( "--------------------------------------------------------------\n" );
    while ( (row = mysql_fetch_row( res ) ) )
    {
        for ( i = 0; i < num_fields; i++ )
        {
            printf( "%s \t", row[i] ? row[i] : NULL );
        }
        printf( "\n" );
    }
    /* 释放结果集 */
    mysql_free_result( res );
    printf( "--------------------------------------------------------------\n" );
    /* 显示受影响的行数 */
    printf( "  %ld rows in set\n", (long) mysql_affected_rows( mysql ) );
}
int main( int argc, char *argv[] )
{
    int     ret, i;
    MYSQL       *mysql;
    MYSQL_RES   * res;
    char        strsql[512] = { 0 };
    /* 1,mysql_init 初始化 */
    mysql = mysql_init( NULL );
    if ( mysql == NULL )
    {
        printf( "mysql_init error\n" );
        return(-1);
    }
    /* 2,mysql_real_connect链接 */
    mysql = mysql_real_connect( mysql,
                    _HOST_,
                    _USER_,
                    _PASSWD_,
                    _DB_,
                    0,
                    NULL,
                    0 );
    if ( mysql == NULL )
    {
        printf( "mysql_real_connect error\n" );
        return(-1);
    }
    printf( "connect mysql ok\n" );
    /* 处理字符问题的函数 */
    if ( mysql_set_character_set( mysql, "utf8" ) != 0 )
    {
        printf( " mysql_set_character_set error\n" );
        mysql_close( mysql );
        exit( 1 );
    }
    /* ===========================输入sql语句====================== */
    while ( 1 )
    {
        memset( strsql, 0x00, sizeof(strsql) );
        write( STDOUT_FILENO, "yoursql>", 8 );
        // select * from IMUser;
        /* 读取client输入的sql字符串 */
        read( STDIN_FILENO, strsql, sizeof(strsql) );
        /* 退出的处理 */
        if ( strncasecmp( strsql, "quit", 4 ) == 0 )
        {
            printf( "client 退出处理\n" );
            break;
        }
        /* 输入sql的 */
        ret = mysql_query( mysql, strsql );
        if ( ret )
        {
            printf( "mysql_query error\n" );
            continue;
        }
        res = mysql_store_result( mysql );
        /*有结果集的处理 */
        if ( res != NULL )
        {
            show_information( res, mysql );
        }else  {
            /* 显示受影响的行数 */
            printf( " Query OK, %ld row affected\n", (long) mysql_affected_rows( mysql ) );
        }
    }
    /* 关闭mysql */
    mysql_close( mysql );
    return(0);
}

2 SQL预处理 防止注入和增加效率

流程图
在这里插入图片描述
在这里插入图片描述

2.1 预处理初始化

MYSQL_STMT *mysql_stmt_init(MYSQL *mysql)

描述
创建MYSQL_STMT句柄。对于该句柄,应使用mysql_stmt_close(MYSQL_STMT *)释放。

返回值
成功时,返回指向MYSQL_STMT结构的指针。如果内存溢出,返回NULL。

2.2 插入预处理语句

int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length)

描述
给定mysql_stmt_init()返回的语句句柄,准备字符串查询指向的SQL语句,并返回状态值。字符串长度应由“length”参量给出。字符串必须包含1条SQL语句。不应为语句添加终结用分号(‘;’)或\g。
通过将问号字符“?”嵌入到SQL字符串的恰当位置,应用程序可包含SQL语句中的一个或多个参数标记符。
标记符仅在SQL语句中的特定位置时才是合法的。例如,它可以在INSERT语句的VALUES()列表中(为行指定列值),或与WHERE子句中某列的比较部分(用以指定比较值)。但是,对于ID(例如表名或列名),不允许使用它们,不允许指定二进制操作符(如等于号“=”)的操作数。后一个限制是有必要的,原因在于,无法确定参数类型。一般而言,参数仅在DML(数据操作语言)语句中才是合法的,在DDL(数据定义语言)语句中不合法。

执行语句之前,必须使用mysql_stmt_bind_param(),将参数标记符与应用程序变量绑定在一起。

返回值
如果成功处理了语句,返回0。如果出现错误,返回非0值。

2.3 获取参数

unsigned long mysql_stmt_param_count(MYSQL_STMT *stmt)

描述
返回预处理语句中参数标记符的数目。

返回值
表示语句中参数数目的无符号长整数。

2.4 参数的绑定

my_bool mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)

描述
mysql_stmt_bind_param()用于为SQL语句中的参数标记符绑定数据,以传递给mysql_stmt_prepare()。它使用MYSQL_BIND结构来提供数据。“bind”是MYSQL_BIND结构的某一数组的地址。按照客户端库的预期,对于查询中出现的每个“?”参数标记符,数组中均包含1个元素。

假定你准备了下述语句:
INSERT INTO mytbl VALUES(?,?,?)
绑定参数时,MYSQL_BIND结构的数组包含3个元素,并能声明如下:
MYSQL_BIND bind[3];

2.5 预处理执行

int mysql_stmt_execute(MYSQL_STMT *stmt)

描述
mysql_stmt_execute()执行与语句句柄相关的预处理查询。在该调用期间,将当前绑定的参数标记符的值发送到服务器,服务器用新提供的数据替换标记符。

如果语句是UPDATE、DELETE或INSERT,通过调用mysql_stmt_affected_rows(),可发现更改、删除或插入的总行数。如果这是诸如SELECT等能生成结果集的语句,调用任何其他能导致查询处理的函数之前,必须调用mysql_stmt_fetch()来获取数据。关于如何获取结果的更多信息,请参见25.2.7.11节,“mysql_stmt_fetch()”。

对于生成结果集的语句,执行语句之前,可通过调用mysql_stmt_attr_set(),请求mysql_stmt_execute()为语句打开光标。如果多次执行某一语句,在打开新的光标前,mysql_stmt_execute()将关闭任何已打开的光标。

返回值
如果执行成功,返回0。如果出现错误,返回非0值。

1.6 返回预处理的行数

my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT *stmt)

描述
返回上次执行语句更改、删除或插入的总行数。对于UPDATE、DELETE或INSERT语句,可在mysql_stmt_execute()之后立刻调用它们。对于SELECT语句,mysql_stmt_affected_rows()的工作方式类似于mysql_num_rows()。

返回值
大于0的整数指明了受影响或检索的行数。对于UPDATE语句,“0”表明未更新任何记录,在查询中没有与WHERE子句匹配的行,或尚未执行任何查询。“-1”表明返回了错误,或对SELECT查询,在调用mysql_stmt_store_result()之前调用了mysql_stmt_affected_rows()。由于mysql_stmt_affected_rows()返回无符号值,可通过比较返回值和“(my_ulonglong)-1”(或等效的“(my_ulonglong)~0”),检查“-1”。

/* gcc -o insert mysql_insert.c -lmysqlclient -I/usr/include/mysql -L/usr/lib64/mysql/ */
/* 预处理方式api处理 -- insert */
#include <stdio.h>
#include "mysql.h"
#include <stdlib.h>
#include <string.h>
#define _HOST_      "localhost"                                     /* 主机 */
#define _USER_      "root"                                          /* mysql用户,非主机 */
#define _PASSWD_    "123456"                                        /* 密码 */
#define _DBNAME_    "teamtalk"                                      /* 库名 */
#define STRING_SIZE 50
#define DROP_SAMPLE_TABLE   "DROP TABLE IF EXISTS test_table"       /* if EXISTS 好处 是如果表不存在,执行不会报错 */
#define CREATE_SAMPLE_TABLE "CREATE TABLE test_table(col1 INT,\
                                                 col2 VARCHAR(40),\
                                                 col3 SMALLINT,\
                                                 col4 TIMESTAMP)"
#define INSERT_SAMPLE       "INSERT INTO test_table(col1,col2,col3) VALUES(?,?,?)"
void prepare_insert( MYSQL *mysql );
int main()
{
    /* 1.初始化 */
    MYSQL * mysql = NULL;
    mysql = mysql_init( NULL );
    if ( mysql == NULL )
    {
        printf( "mysql init err\n" );
        exit( 1 );
    }
    /* 2.连接 */
    mysql = mysql_real_connect( mysql, _HOST_, _USER_, _PASSWD_, _DBNAME_, 0, NULL, 0 );
    if ( mysql == NULL )
    {
        printf( "mysql_real_connect connect err\n" );
        exit( 1 );
    }
    printf( "welcome to mysql \n" );
    prepare_insert( mysql );
    /* 3.关闭 */
    mysql_close( mysql );
    return(0);
}
void prepare_insert( MYSQL *mysql )
{
    MYSQL_STMT  *stmt;          /* 预处理的句柄 -- 标识进程内唯一的一个预处理的sql */
    MYSQL_BIND  bind[3];        /* 绑定变量 */
    my_ulonglong    affected_rows;
    int     param_count;
    short       small_data;
    int     int_data;
    char        str_data[STRING_SIZE];
    unsigned long   str_length;
    my_bool     is_null;
    if ( mysql_query( mysql, DROP_SAMPLE_TABLE ) )          /*删除表 */
    {
        fprintf( stderr, " DROP TABLE failed\n" );
        fprintf( stderr, " %s\n", mysql_error( mysql ) );
        exit( 0 );
    }
    if ( mysql_query( mysql, CREATE_SAMPLE_TABLE ) )        /* 创建表 */
    {
        fprintf( stderr, " CREATE TABLE failed\n" );
        fprintf( stderr, " %s\n", mysql_error( mysql ) );
        exit( 0 );
    }
    /* Prepare an INSERT query with 3 parameters */
    /* (the TIMESTAMP column is not named; the server */
    /*  sets it to the current date and time) */
    stmt = mysql_stmt_init( mysql );                                                /* 预处理的初始化 */
    if ( !stmt )
    {
        fprintf( stderr, " mysql_stmt_init(), out of memory\n" );
        exit( 0 );
    }
    if ( mysql_stmt_prepare( stmt, INSERT_SAMPLE, strlen( INSERT_SAMPLE ) ) )       /* insert 语句 的预处理 */
    {
        fprintf( stderr, " mysql_stmt_prepare(), INSERT failed\n" );
        fprintf( stderr, " %s\n", mysql_stmt_error( stmt ) );
        exit( 0 );
    }
    fprintf( stdout, " prepare, INSERT successful\n" );
    /* Get the parameter count from the statement */
    param_count = mysql_stmt_param_count( stmt );   /* 获得参数个数 */
    fprintf( stdout, " total parameters in INSERT: %d\n", param_count );
    if ( param_count != 3 )                         /* validate parameter count */
    {
        fprintf( stderr, " invalid parameter count returned by MySQL\n" );
        exit( 0 );
    }
    /* Bind the data for all 3 parameters */
    memset( bind, 0, sizeof(bind) );
    /* INTEGER PARAM */
    /* This is a number type, so there is no need to specify buffer_length */
    bind[0].buffer_type = MYSQL_TYPE_LONG;      /* 对应int类型 */
    bind[0].buffer      = (char *) &int_data;   /* 内存地址的映射 */
    bind[0].is_null     = 0;
    bind[0].length      = 0;
    /* STRING PARAM */
    bind[1].buffer_type = MYSQL_TYPE_STRING;
    bind[1].buffer      = (char *) str_data;    /* char 100 */
    bind[1].buffer_length   = STRING_SIZE;
    bind[1].is_null     = 0;
    bind[1].length      = &str_length;
    /* SMALLINT PARAM */
    bind[2].buffer_type = MYSQL_TYPE_SHORT;
    bind[2].buffer      = (char *) &small_data;
    bind[2].is_null     = &is_null;             /* 是否为null的指示器 */
    bind[2].length      = 0;
    /* Bind the buffers */
    if ( mysql_stmt_bind_param( stmt, bind ) )      /* 绑定变量 参数绑定 */
    {
        fprintf( stderr, " mysql_stmt_bind_param() failed\n" );
        fprintf( stderr, " %s\n", mysql_stmt_error( stmt ) );
        exit( 0 );
    }
    /* 第一波赋值 */
    int_data = 10;                                  /* integer */
    strncpy( str_data, "MySQL", STRING_SIZE );      /* string  */
    str_length = strlen( str_data );
    /* INSERT INTO test_table(col1,col2,col3) VALUES(10,'MySQL',null) */
    /* INSERT SMALLINT data as NULL */
    is_null = 1;                                    /* 指示插入的第三个字段是否为null */
    /* insert into test_table(col1,col2,col3) values(10,'MySQL',null); */
    /* Execute the INSERT statement - 1*/
    if ( mysql_stmt_execute( stmt ) )               /* 预处理的执行,第一次执行 */
    {
        fprintf( stderr, " mysql_stmt_execute(), 1 failed\n" );
        fprintf( stderr, " %s\n", mysql_stmt_error( stmt ) );
        exit( 0 );
    }
    /* Get the total number of affected rows */
    affected_rows = mysql_stmt_affected_rows( stmt );       /* 预处理的影响条数 */
    fprintf( stdout, " total affected rows(insert 1): %lu\n",
         (unsigned long) affected_rows );
    if ( affected_rows != 1 )                               /* validate affected rows */
    {
        fprintf( stderr, " invalid affected rows by MySQL\n" );
        exit( 0 );
    }
    /* 第二波赋值 */
    int_data = 1000;
    strncpy( str_data, "The most popular Open Source database", STRING_SIZE );
    str_length  = strlen( str_data );
    small_data  = 1000; /* smallint */
    is_null     = 1;    /* reset */
    /* INSERT INTO test_table(col1,col2,col3) VALUES(1000,'The most popular Open Source database',1000) */
    /* insert into test_table(col1,col2,col3) values(1000,'The most popular Open Source database',1000); */
    /* Execute the INSERT statement - 2*/
    if ( mysql_stmt_execute( stmt ) ) /* 第二次执行 */
    {
        fprintf( stderr, " mysql_stmt_execute, 2 failed\n" );
        fprintf( stderr, " %s\n", mysql_stmt_error( stmt ) );
        exit( 0 );
    }
    /* Get the total rows affected */
    affected_rows = mysql_stmt_affected_rows( stmt );
    fprintf( stdout, " total affected rows(insert 2): %lu\n",
         (unsigned long) affected_rows );
    if ( affected_rows != 1 ) /* validate affected rows */
    {
        fprintf( stderr, " invalid affected rows by MySQL\n" );
        exit( 0 );
    }
    /* Close the statement */
    if ( mysql_stmt_close( stmt ) )
    {
        fprintf( stderr, " failed while closing the statement\n" );
        fprintf( stderr, " %s\n", mysql_stmt_error( stmt ) );
        exit( 0 );
    }
}

3 查询预处理

流程图
在这里插入图片描述
api介绍

MYSQL_RES *mysql_stmt_param_metadata(MYSQL_STMT *stmt)

提前指定结果集的操作

/* gcc -o select mysql_select.c -lmysqlclient -I/usr/include/mysql -L/usr/lib64/mysql/ */
/* SELECT id, name, sex FROM IMUser; 查询语句的使用 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql.h>
#define _USER_      "root"          /* 用户名 */
#define _HOST_      "127.0.0.1"     /* host */
#define _PASSWD_    "123456"        /* root 用户名密码 */
#define _DB_        "teamtalk"      /* 库名 */
#define _PORT_      3306            /* port */
/* ============================stmt ====================================== */
#define STRING_SIZE 50
/* mysql 查询语句 */
#define SELECT_SAMPLE "SELECT id, name, sex FROM IMUser"
void seach_information( MYSQL *mysql )
{
    int     i, count = 0;;
    MYSQL_STMT  *stmt;                  /*  */
    MYSQL_BIND  bind[3];                /* 条件变量 */
    MYSQL_RES   *prepare_meta_result;   /* 结果集 */
    unsigned long   length[3];
    int     param_count, column_count, row_count;
    int     int_data;               /* 序号 */
    char        str_name[STRING_SIZE];  /* 姓名 */
    char        str_loc[STRING_SIZE];
    my_bool     is_null[3];             /* 参数的控制 */
    my_ulonglong    row_unm;
    /*
     * ===========================init start=========================
     * 初始化sql预处理语句
     */
    stmt = mysql_stmt_init( mysql );
    if ( !stmt )
    {
        fprintf( stderr, " mysql_stmt_init(), out of memory\n" );
        exit( 0 );
    }
    /*
     * 绑定参数my_bool mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
     * mysql_stmt_bind_param(stmt, bind);
     */
    if ( mysql_stmt_prepare( stmt, SELECT_SAMPLE, strlen( SELECT_SAMPLE ) ) )
    {
        fprintf( stderr, " mysql_stmt_prepare(), SELECT failed\n" );
        fprintf( stderr, " %s\n", mysql_stmt_error( stmt ) );
        exit( 0 );
    }
    fprintf( stdout, " prepare, SELECT successful\n" );
    fprintf( stdout, " total parameters in SELECT: %d\n", param_count );
    param_count = mysql_stmt_param_count( stmt );
    if ( param_count != 0 ) /* validate parameter count */
    {
        fprintf( stderr, " invalid parameter count returned by MySQL\n" );
        exit( 0 );
    }
    prepare_meta_result = mysql_stmt_result_metadata( stmt );
    if ( !prepare_meta_result )
    {
        fprintf( stderr,
             " mysql_stmt_result_metadata(), returned no meta information\n" );
        fprintf( stderr, " %s\n", mysql_stmt_error( stmt ) );
        exit( 0 );
    }
    column_count = mysql_num_fields( prepare_meta_result );
    fprintf( stdout, " total columns in SELECT statement: %d\n", column_count );
    if ( column_count != 3 ) /* validate column count */
    {
        fprintf( stderr, " invalid column count returned by MySQL\n" );
        exit( 0 );
    }
    /* mysql_stmt_execute(stmt); //发送占位符到mysql数据库上???? */
    if ( mysql_stmt_execute( stmt ) )
    {
        fprintf( stderr, " mysql_stmt_execute(), failed\n" );
        fprintf( stderr, " %s\n", mysql_stmt_error( stmt ) );
        exit( 0 );
    }
    /* 初始化参数 */
    memset( bind, 0, sizeof(bind) );
    /* INTEGER COLUMN */
    bind[0].buffer_type = MYSQL_TYPE_LONG;
    bind[0].buffer      = (char *) &int_data;
    bind[0].is_null     = &is_null[0];
    bind[0].length      = &length[0];
    /* varchar    -- MYSQL_TYPE_VAR_STRING */
    /* name COLUMN */
    bind[1].buffer_type = MYSQL_TYPE_VAR_STRING;
    bind[1].buffer      = (char *) str_name;
    bind[1].buffer_length   = STRING_SIZE;
    bind[1].is_null     = &is_null[1];
    bind[1].length      = &length[1];
    /* loc COLUMN */
    bind[2].buffer_type = MYSQL_TYPE_VAR_STRING;
    bind[2].buffer      = (char *) &str_loc;
    bind[2].buffer_length   = STRING_SIZE;
    bind[2].is_null     = &is_null[2];
    bind[2].length      = &length[2];
    /* 绑定数据 */
    mysql_stmt_bind_result( stmt, bind );
    mysql_stmt_store_result( stmt ); /*  */
    /* init row */
    row_count = 0;
    /* 查询的结果 */
    row_unm = mysql_stmt_num_rows( stmt );
    /*
     * 打印数据
     * mysql_stmt_fetch(stmt);
     * mysql_stmt_fetch(stmt);
     */
    printf( "row_unm = %ld\n", row_unm );
    for ( i = 0; i < row_unm; i++ )
    {
        mysql_stmt_fetch( stmt );
        row_count++;
        fprintf( stdout, "  row %d\n", row_count );
        /* column 1 */
        fprintf( stdout, "   column1 (integer)  : " );
        if ( is_null[0] )
            fprintf( stdout, " NULL\n" );
        else
            fprintf( stdout, " %d(%ld)\n", int_data, length[0] );
        /* column 2 */
        fprintf( stdout, "   column2 (string)   : " );
        if ( is_null[1] )
            fprintf( stdout, " NULL\n" );
        else
            fprintf( stdout, " %s(%ld)\n", str_name, length[1] );
        /* column 3 */
        fprintf( stdout, "   column3 (string) : " );
        if ( is_null[2] )
            fprintf( stdout, " NULL\n" );
        else
            fprintf( stdout, " %s(%ld)\n", str_loc, length[2] );
        fprintf( stdout, "\n" );
        /* break; */
    }
    /* 释放内存 */
    /* Validate rows fetched */
    // if ( row_count != 10 )
    // {
    //  fprintf( stderr, " MySQL failed to return all rows\n" );
    //  exit( 0 );
    // }
    /* Free the prepared result metadata */
    mysql_free_result( prepare_meta_result );
    /* Close the statement */
    mysql_stmt_close( stmt );
}
/* ===================================================================== */
int main( int argc, char *argv[] )
{
    int     ret, i;
    MYSQL       *mysql;
    MYSQL_RES   * res;
    MYSQL_ROW   row;    /*  */
    /* unsigned long *lengths; */
    unsigned int    num_fields;
    MYSQL_FIELD *field; /* 字段名 */
    /* 1,mysql_init 初始化 */
    mysql = mysql_init( NULL );
    if ( mysql == NULL )
    {
        printf( "mysql_init error\n" );
        return(-1);
    }
    /* 2,mysql_real_connect链接 */
    mysql = mysql_real_connect( mysql,
                    _HOST_,
                    _USER_,
                    _PASSWD_,
                    _DB_,
                    0,
                    NULL,
                    0 );
    if ( mysql == NULL )
    {
        printf( "mysql_real_connect error\n" );
        return(-1);
    }
    printf( "connect mysql ok\n" );
    /* 设置一下字符编码utf8 */
    if ( mysql_set_character_set( mysql, "utf8" ) )
    {
        printf( "   mysql_set_character_set error\n");
        return(-1);
    }
    seach_information( mysql );
    /* 关闭mysql */
    mysql_close( mysql );
    return(0);
}

4 事务的介绍

/* gcc -o transaction mysql_transaction.c -lmysqlclient -I/usr/include/mysql -L/usr/lib64/mysql/ */
/* mysql中的事务 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mysql.h"
#define SET_TRAN    "SET AUTOCOMMIT=0"      /* 手动commit ————手动commit */
#define UNSET_TRAN  "SET AUTOCOMMIT=1"      /* 自动commit */
#define _HOST_      "127.0.0.1"
#define _USER_      "root"
#define _PASSWD_    "123456"
#define _DBNAME_    "teamtalk"
/* 设置事务为手动提交 */
int mysql_OperationTran( MYSQL *mysql )
{
    /* --开启事务 */
    int ret = mysql_query( mysql, "start transaction" ); /* 开启一次事务 start transaction */
    if ( ret != 0 )
    {
        printf( "mysql_OperationTran query start err: %s\n", mysql_error( mysql )     );
        return(ret);
    }
    /* --设置事务为手动提交 */
    ret = mysql_query( mysql, SET_TRAN ); /* set autocommmit = 0 */
    if ( ret != 0 )
    {
        printf( "mysql_OperationTran query set err: %s\n", mysql_error( mysql ) );
        return(ret);
    }
    return(ret);
}
/* 设置事务为自动提交 */
int mysql_AutoTran( MYSQL *mysql )
{
    /* --开启事务 */
    int ret = mysql_query( mysql, "start transaction" );
    if ( ret != 0 )
    {
        printf( "mysql_AutoTran query start err: %s\n", mysql_error( mysql ) );
        return(ret);
    }
    /* --设置事务为自动提交 */
    ret = mysql_query( mysql, UNSET_TRAN ); /* "set autocommit = 1" */
    if ( ret != 0 )
    {
        printf( "mysql_AutoTran query set err: %s\n", mysql_error( mysql ) );
        return(ret);
    }
    return(ret);
}
/* 执行commit,手动提交事务 */
int mysql_Commit( MYSQL *mysql )
{
    int ret = mysql_query( mysql, "COMMIT" ); /* 提交 */
    if ( ret != 0 )
    {
        printf( "commit err: %s\n", mysql_error( mysql ) );
        return(ret);
    }
    return(ret);
}
/* 执行rollback,回滚事务 */
int mysql_Rollback( MYSQL *mysql )
{
    int ret = mysql_query( mysql, "ROLLBACK" );
    if ( ret != 0 )
    {
        printf( "rollback err: %s\n", mysql_error( mysql ) );
        return(ret);
    }
    return(ret);
}
#define DROP_SAMPLE_TABLE   "DROP TABLE IF EXISTS test_table"
#define CREATE_SAMPLE_TABLE "CREATE TABLE test_table(col1 INT,\
                                                 col2 VARCHAR(10),\
                                                 col3 VARCHAR(10))"
#define sql01   "INSERT INTO test_table(col1,col2,col3) VALUES(10, 'AAA', 'A1')"
#define sql02   "INSERT INTO test_table(col1,col2,col3) VALUES(20, 'BBB', 'B2')"
#define sql03   "INSERT INTO test_table(col1,col2,col3) VALUES(30, 'CCC', 'C3')"
#define sql04   "INSERT INTO test_table(col1,col2,col3) VALUES(40, 'DDD', 'D4')"
int main( void )
{
    int ret = 0;
    MYSQL *mysql = mysql_init( NULL );
    mysql = mysql_real_connect( mysql, _HOST_, _USER_, _PASSWD_, _DBNAME_, 0, NULL, 0 );
    if ( mysql == NULL )
    {
        ret = mysql_errno( mysql );
        printf( "func mysql_real_connect() err:%d\n", ret );
        return(ret);
    }
    printf( " --- connect ok......\n" );
    /* 执行删除表 */
    if ( mysql_query( mysql, DROP_SAMPLE_TABLE ) )
    {
        fprintf( stderr, " DROP TABLE failed\n" );
        fprintf( stderr, " %s\n", mysql_error( mysql ) );
        exit( 0 );
    }
    /* 执行创建表 */
    if ( mysql_query( mysql, CREATE_SAMPLE_TABLE ) )
    {
        fprintf( stderr, " CREATE TABLE failed\n" );
        fprintf( stderr, " %s\n", mysql_error( mysql ) );
        exit( 0 );
    }
    ret = mysql_OperationTran( mysql );     /* 开启事务,并修改事务属性为手动commit */
    if ( ret != 0 )
    {
        printf( "mysql_OperationTran() err:%d\n", ret );
        return(ret);
    }
    ret = mysql_query( mysql, sql01 );      /* 向表中插入第一行数据 ‘AAA’ */
    if ( ret != 0 )
    {
        printf( "mysql_query() err:%d\n", ret );
        return(ret);
    }
    ret = mysql_query( mysql, sql02 );      /* 向表中插入第二行数据 ‘BBB’ */
    if ( ret != 0 )
    {
        printf( "mysql_query() err:%d\n", ret );
        return(ret);
    }
    ret = mysql_Commit( mysql );            /* 手动提交事务 */
    if ( ret != 0 )
    {
        printf( "mysql_Commit() err:%d\n", ret );
        return(ret);
    }
    /* AAA BBB  进去了。 */
#if 1
    ret = mysql_AutoTran( mysql );          /* =再次= 修改事务属性为【自动】commit */
    if ( ret != 0 )
    {
        printf( "mysql_OperationTran() err:%d\n", ret );
        return(ret);
    }
#else
    ret = mysql_OperationTran( mysql );     /* =再次= 修改事务属性为【手动】commit */
    if ( ret != 0 )
    {
        printf( "mysql_OperationTran() err:%d\n", ret );
        return(ret);
    }
#endif
    ret = mysql_query( mysql, sql03 );      /* 向表中插入第三行数据 ‘CCC’ */
    if ( ret != 0 )
    {
        printf( "mysql_query() err:%d\n", ret );
        return(ret);
    }
    ret = mysql_query( mysql, sql04 );      /* 向表中插入第四行数据 ‘DDD’ */
    if ( ret != 0 )
    {
        printf( "mysql_query() err:%d\n", ret );
        return(ret);
    }
    ret = mysql_Rollback( mysql );          /* 直接rollback操作 */
    if ( ret != 0 )
    {
        printf( "mysql_Rollback() err:%d\n", ret );
        return(ret);
    }
    /* rollback操作是否能回退掉CCC、DDD的值,取决于事务属性。 */
    mysql_close( mysql );
    return(0);
}

5 增删改查

5.1 增

使用预处理

strSql = "insert into IMUser(`salt`,`sex`,`nick`,`password`,`domain`,`name`,`phone`,`email`,`company`,`address`,`avatar`,`sign_info`,`departId`,`status`,`created`,`updated`) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";

5.2 删

5.3 改

-更新,直接sql语句更新

mysql_real_query
范例

string str_sql = "update IMUser set `sign_info`='" + sign_info + "', `updated`=" + int2string(now) + " where id="+int2string(user_id);
bool CDBConn::ExecuteUpdate( const char* sql_query, bool care_affected_rows )
{
    mysql_ping( m_mysql );
    if ( mysql_real_query( m_mysql, sql_query, strlen( sql_query ) ) )
    {
        log_error( "mysql_real_query failed: %s, sql: %s", mysql_error( m_mysql ), sql_query );
        /* g_master_conn_fail_num ++; */
        return(false);
    }
    if ( mysql_affected_rows( m_mysql ) > 0 )
    {
        return(true);
    }else  {                                /* 影响的行数为0时 */
        if ( care_affected_rows )       /* 如果在意影响的行数时, 返回false, 否则返回true */
        {
            log_error( "mysql_real_query failed: %s, sql: %s", mysql_error( m_mysql ), sql_query );
            return(false);
        }else  {
            log_warn( "affected_rows=0, sql: %s", sql_query );
            return(true);
        }
    }
}

5.4 查

enum enum_field_types { 
    MYSQL_TYPE_DECIMAL, 
    MYSQL_TYPE_TINY,
    MYSQL_TYPE_SHORT,  
    MYSQL_TYPE_LONG,
    MYSQL_TYPE_FLOAT,  
    MYSQL_TYPE_DOUBLE,
    MYSQL_TYPE_NULL,   
    MYSQL_TYPE_TIMESTAMP,
    MYSQL_TYPE_LONGLONG,
    MYSQL_TYPE_INT24,
    MYSQL_TYPE_DATE,   
    MYSQL_TYPE_TIME,
    MYSQL_TYPE_DATETIME, 
    MYSQL_TYPE_YEAR,
    MYSQL_TYPE_NEWDATE, 
    MYSQL_TYPE_VARCHAR,
    MYSQL_TYPE_BIT,
    MYSQL_TYPE_TIMESTAMP2,
    MYSQL_TYPE_DATETIME2,
    MYSQL_TYPE_TIME2,
    MYSQL_TYPE_NEWDECIMAL=246,
    MYSQL_TYPE_ENUM=247,
    MYSQL_TYPE_SET=248,
    MYSQL_TYPE_TINY_BLOB=249,
    MYSQL_TYPE_MEDIUM_BLOB=250,
    MYSQL_TYPE_LONG_BLOB=251,
    MYSQL_TYPE_BLOB=252,
    MYSQL_TYPE_VAR_STRING=253,
    MYSQL_TYPE_STRING=254,
    MYSQL_TYPE_GEOMETRY=255
}

typedef struct st_mysql_field {
  char *name;                 /* Name of column 列名 */
  char *org_name;             /* Original column name, if an alias */
  char *table;                /* Table of column if column was a field */
  char *org_table;            /* Org table name, if table was an alias */
  char *db;                   /* Database for table */
  char *catalog;           /* Catalog for table */
  char *def;                  /* Default value (set by mysql_list_fields) */
  unsigned long length;       /* Width of column (create length) */
  unsigned long max_length;   /* Max width for selected set */
  unsigned int name_length;
  unsigned int org_name_length;
  unsigned int table_length;
  unsigned int org_table_length;
  unsigned int db_length;
  unsigned int catalog_length;
  unsigned int def_length;
  unsigned int flags;         /* Div flags */
  unsigned int decimals;      /* Number of decimals in field */
  unsigned int charsetnr;     /* Character set */
  enum enum_field_types type; /* Type of field. See mysql_com.h for types */   // 字段的mysql 数据类型
  void *extension;
} MYSQL_FIELD;


int    mysql_real_query(MYSQL *mysql, const char *q, unsigned long length);
    说明:执行SQL
    参数1:已初始化的MYSQL 实例;
    参数2:SQL 语句;
    参数3:SQL 语句字符数。

MYSQL_RES *mysql_store_result(MYSQL *mysql);
    说明:对于成功检索了数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN、CHECK TABLE等),
    必须调用mysql_store_result()mysql_use_result()
    参数:已初始化的MYSQL 实例。

// typedef char **MYSQL_ROW; 
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
    说明:检索一个结果集合的下一行。当在mysql_store_result()之后使用时,
	如果没有更多的行可检索时,mysql_fetch_row()返回NULL。当在mysql_use_result()之后使用时,
	当没有更多的行可检索时或如果出现一个错误,mysql_fetch_row()返回NULL
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值