无法通过MariaDB connect/c预处理语句转换字符串

8ljdwjyq  于 2022-11-08  发布在  其他
关注(0)|答案(1)|浏览(132)

我正在使用“MariaDB Connector/C”做作业,但遇到了一个问题:当我传入一个字符串参数时,总是得到一个空字符串,数据库表是:

MariaDB none@(none):test> SELECT * FROM t3

| 一种|最佳|
| - -|- -|
| 第0页|abc公司|
| 一个|二进制编码|
| 2个|自动增益控制|
第一个
| 字段|型号|空值|关键字|默认值|额外的|
| - -|- -|- -|- -|- -|- -|
| 一种|整数(11)|否|优先级|||
| 最佳|充电器(10)|是的||||

2 rows in set
Time: 0.011s

而我用来测试的代码:


# include <mysql/mysql.h>

# include <stdio.h>

# include <stdlib.h>

# include <string.h>

int main()
{
    MYSQL *mysql;
    mysql = mysql_init(NULL);
    if (!mysql_real_connect(mysql,NULL , "none", "linux", "test", 0,"/tmp/mariadb.sock",0)){
        printf( "Error connecting to database: %s",mysql_error(mysql));
    } else
        printf("Connected...\n");
    if(mysql_real_query(mysql,"SET CHARACTER SET utf8",(unsigned int)sizeof("SET CHARACTER SET utf8"))){
        printf("Failed to set Encode!\n");
    }

    char query_stmt_2[]="select * from t3 where b=?";
    MYSQL_STMT *stmt2 = mysql_stmt_init(mysql);
    if(mysql_stmt_prepare(stmt2, query_stmt_2, -1))
    {
        printf("STMT2 prepare failed.\n");
    }
    MYSQL_BIND instr_bind;
    char instr[50]="abc";
    my_bool in_is_null = 0;
    my_bool in_error = 0;
    instr_bind.buffer_type = MYSQL_TYPE_STRING;
    instr_bind.buffer = &instr[0];
    char in_ind = STMT_INDICATOR_NTS;
    instr_bind.u.indicator = &in_ind;
    unsigned long instr_len=sizeof(instr);
    // instr_bind.length = &instr_len;
    // instr_bind.buffer_length=instr_len;
    instr_bind.is_null = &in_is_null;
    instr_bind.error = &in_error;

    MYSQL_BIND out_bind[2];
    memset(out_bind, 0, sizeof(out_bind));
    int out_int[2];
    char outstr[50];
    my_bool out_int_is_null[2]={0,0};
    my_bool out_int_error[2]={0,0};
    unsigned long out_int_length[2]={0,0};
    out_bind[0].buffer = out_int+0;
    out_bind[0].buffer_type = MYSQL_TYPE_LONG;
    out_bind[0].is_null = out_int_is_null+0;
    out_bind[0].error = out_int_error+0;
    out_bind[0].length = out_int_length+0;

    out_bind[1].buffer = outstr;
    out_bind[1].buffer_type = MYSQL_TYPE_STRING;
    out_bind[1].buffer_length = 50;
    out_bind[1].is_null = out_int_is_null+1;
    out_bind[1].error = out_int_error+1;
    out_bind[1].length = out_int_length+1;

    if(mysql_stmt_bind_param(stmt2, &instr_bind) ||
    mysql_stmt_bind_result(stmt2, out_bind)){
        printf("Bind error\n");
    }

    if(mysql_stmt_execute(stmt2))
    {
        printf("Exec error: %s",mysql_stmt_error(stmt2));
    }

    if(mysql_stmt_store_result(stmt2)){
        printf("Store result error!\n");
        printf("%s\n",mysql_stmt_error(stmt2));
    }
    while(!mysql_stmt_fetch(stmt2))
    {
        printf("%d\t%s\n", out_int[0], outstr);
    }
    mysql_stmt_close(stmt2);
end:
    mysql_close(mysql);

}

我只得到了一个空的结果:

❯ ./Exec/test/stmt_test
Connected...

这两天我一直在为这事发愁,明天就是最后期限了,我很着急。你能帮忙吗?谢谢!

wecizke3

wecizke31#

1)概述

  • 避免“写起来很难,所以读起来也应该很难”的代码
  • 在函数的开头添加变量声明,而不是在代码的中间(W声明在语句之后)
  • 不要在C中使用C++注解
  • 使用api函数mysql_set_character_set()设置字符集
  • 编写正确的错误处理,包括mysql_error/mysql_stmt_error结果,并且在出错后不要继续执行后续代码。
  • 总是初始化MYSQL_BIND
    2)输入绑定缓冲区
  • u.指示符用于批量操作,在这里没有意义
  • bind.is_null不是必需的,因为您指定了有效的缓冲区地址
  • 未设置buffer_length(在注解中)
    3)输出绑定缓冲区
  • 总是在mysql_stmt_execute()之后绑定输出参数,因为mysql_stmt_prepare不能总是确定参数的数量,例如,当调用存储过程时:在这种情况下,mysql_stmt_bind_param将返回一个错误。
  • 如果不设置MYSQL_REPORT_DATA_TRUNCATION(mysql_optionsv),则绑定错误指示器没有多大意义

有关如何处理预准备语句的一些示例,请查看MariaDB Connector/C unit tests的文件ps. c

相关问题