项目使用的是Qt,操作MySQL用的是现有的接口,是将MySQL语句封装在动态库里的,今天看了看最底层的情况,才发现操作MySQL不是用Qt,而是它自带的C++ API,之前没直接用过原生API,今天记录一下。
代码连接数据库用的函数是MyConnection::connect_in(),用到的函数是mysql_init, mysql_real_connect, mysql_close, mysql_select_db, mysql_set_server_option。
登录MySQL数据库1
2
3
4
5
6
7
8
9
10
11MYSQL * STDCALL (MYSQL *mysql);
MYSQL * STDCALL mysql_real_connect(MYSQL *mysql,
const char *host, //MySQL的IP,远程登录输入远程登录的IP地址
const char *user, //登录用户
const char *passwd, //登录密码
const char *db, //使用的数据库名称
unsigned int port, //MySQL端口
const char *unix_socket, //是否使用socket机制登录,NULL:否
unsigned long clientflag); //连接标志,通常为0
设置活动的MySQL数据库1intSTDCALL mysql_select_db(MYSQL *mysql, const char *db);
操作MySQL1
2
3
4int STDCALL mysql_query(MYSQL *mysql, //MySQL操作结构体
const char *q); //操作命令
//成功返回0,失败返回1
设置多语句
mysql_query通常使用单独的SQL语句(不带“;”的),也可调用mysql_set_server_option(&mysql,MYSQL_OPTION_MULTI_STATEMENTS_ON)指定以分号分隔的多个SQL语句
获得语句错误1
2unsigned int mysql_errno(MYSQL *mysql); // 错误码
char *mysql_error(MYSQL *mysql); // 文本错误信息
可以通过调用mysql_errn传递连接来获得错误码,它通常都是非0值。如果未设定错误码,它将返回0。
调用mysql_error提供有意义的文本信息而不是单调的错误码
关闭MySQL1void STDCALL mysql_close(MYSQL *sock);
取得SELECT执行结果
这个比较重要,也比较麻烦1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25MYSQL m_sql;
// 初始化、连接、设置编码
int res = mysql_query(&m_sql, sql_cmd);// sql_cmd是SELECT SQL语句
if(!res)// res为0则执行成功
{
result = mysql_store_result(&m_sql);
int rows = mysql_num_rows(result); // SELECT SQL执行后,有几条结果
if(rows >= 1) // 数据库中有符合条件的数据
{
// 每行结果有几列
unsigned int num_fields = mysql_num_fields(result);
MYSQL_ROW row;
while( row = mysql_fetch_row(result) )
{
for(int i=0;i
{
// 下标为0对应表的第一列,这里是time,以此类推
ROS_INFO("id in database: %sn",row[0]);
ROS_INFO("time in database: %sn",row[1]);
}
}
}
else
ROS_INFO("数据库中没有结果");
}
比如执行SELECT SQL后,得到下面结果:
rows为5,mysql_fetch_row会依次取每行的结果, 无法直接访问某一行的结果,row[0]对应每行的id列
查看sql执行是否有影响
如果执行DELETE命令,删除一个不存在的行,不会报错,但也不会产生影响。所以我们需要判断结果到底如何,否则就得DELETE之前SELECT看要删除的行是否存在。下面的命令执行后就是没有影响:
mysql_affected_rows(MYSQL*)取得最近一次的 INSERT,UPDATE 或 DELETE 执行后所影响的记录行数。执行成功,则返回受影响的行的数目,如果最近一次查询失败的话,函数返回 -1
对于delete,将返回实际删除的行数.
对于update,如果更新的列值原值和新值一样,如 update tables set col1=10 where id=1;id=1 该条记录原值就是10的话,则返回0。mysql_affected_rows返回的是实际更新的行数,而不是匹配到的行数。
对于mysql的事务而言,列值相等的更新,不能依赖mysql_affected_rows的返回值。如果使用该函数,应该先判断列值,或者直接使用mysql_query的返回值.
释放为结果集分配的内存
使用void mysql_free_result(MYSQL_RES *result),释放由mysql_store_result()、mysql_use_result()、mysql_list_dbs()等为结果集分配的内存。这是必不可少的操作,释放完成后,不要尝试访问结果集。
测试连接
int mysql_ping(MYSQL *mysql);函数 Ping 一个服务器连接,如果没有连接则重新连接。可用于空闲很久的脚本来检查MySQL服务器是否关闭了连接:1
2
3
4
5
6
7int ret = mysql_ping(&mysql);
if (ret ==0 ) {
return true;
}
qWarning("连接错误:%s", mysql_error(&mysql));
mysql_close(&mysql);
hasConnect=false;