参考连接MYSQL 常用API
一、初始化
MYSQL * mysql_init(MYSQL *mysql); // 初始化一个MYSQL 连接的实例对象
void mysql_close(MYSQL *sock); // 释放一个MYSQL 连接实例
二、连接
mysql_real_connect()函数:
#include<mysql.h>
函数原型描述:
MYSQL *mysql_real_connect (
MYSQL *mysql, //MYSQL *为mysql_init函数返回的指针
const char *host, //host为null或 localhost时链接的是本地的计算机
const char *user, //当mysql默认安装在unix(或类unix)系统中,root账户是没有密码的,因此用户名使用root,密码为null,
const char *passwd, //密码
const char *db, //当db为空的时候,函数链接到默认数据库,在进行 mysql安装时会存在默认的test数据库,因此此处可以使用test数据库名称,
unsigned int port, //port端口为0,
const char *unix_socket, // unix连接方式,unix_socket为null时,表明不使用socket或管道机制,最后一个参数经常设置为0
unsigned long client_flag)
mysql_real_connect()尝试与运行在主机上的MySQL数据库引擎建立连接。在你能够执行需要有效MySQL连接句柄结构的任何其他API函数之前,mysql_real_connect()必须成功完成。
返回值
如果连接成功,返回MYSQL*连接句柄。如果连接失败,返回NULL。对于成功的连接,返回值与第1个参数的值相同。
三、测试代码
#include <iostream>
#include<mysql.h>
using namespace std;
int main()
{
//初始化mysql上下文
MYSQL mysql;
//单线程模式 mysql_init自动调用 mysql_library_init 线程不安全
mysql_init(&mysql);
const char* host = "127.0.0.1";
const char* user = "root";
const char* pass = "122324"; //密码
const char* db = "mysql"; //数据库名称
if (!mysql_real_connect(&mysql, host, user, pass, db, 3306, 0, 0))
{
cout << "mysql connect failed!" << mysql_error(&mysql) << endl;
}
else
{
cout << "mysql connect success!" << endl;
}
mysql_close(&mysql);
mysql_library_end();
std::cout << "Hello World!\n";
getchar();
}
四、超时设定和自动重连
int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg)
用于设置额外的连接选项,并影响连接的行为。可多次调用该函数来设置数个选项。
可预设的选项
三、mysql数据查询接口
1.执行sql语句
int mysql_real_query(MYSQL *mysql, const char *query, unsigned long length)
//执行由“query”指向的SQL查询,它应是字符串长度字节“long”。
//正常情况下,字符串必须包含1条SQL语句,而且不应为语句添加
//终结分号(‘;’)或“\g”。如果允许多语句执行,字符串可包含
//由分号隔开的多条语句。
//如果查询成功,返回0。如果出现错误,返回非0值。
int mysql_query(MYSQL *mysql, const char *query)
//执行由“Null终结的字符串”查询指向的SQL查询
//如果查询成功,返回0。如果出现错误,返回非0值。
mysql_query()不能用于包含二进制数据的查询,应使用mysql_real_query()取而代之(二进制数据可能包含字符‘\0’,mysql_query()会将该字符解释为查询字符串结束)。
二、获取结果集
对于成功检索数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN),必须调用mysql_store_result()或mysql_use_result()。
MYSQL_RES *mysql_use_result(MYSQL *mysql)
MYSQL_RES *mysql_store_result(MYSQL *mysql)
//返回:MYSQL_RES结果结构。如果出现错误,返回NULL。
//区别:
/*第一种,调用mysql_store_result函数将从Mysql服务器查询的所有数据都存储到客户端,然后读取;他需要考虑缓存的大小,由max_allowed_packet限定。
第二种,调用mysql_use_result初始化检索,以便于后面一行一行的读取结果集,而它本身并没有从服务器读取任何数据,
这种方式较之第一种速度更快且所需内存更少,但它会绑定服务器,阻止其他线程更新任何表,而且必须重复执行
mysql_fetch_row读取数据,直至返回NULL,否则未读取的行会在下一次查询时作为结果的一部分返回,
故经常我们使用mysql_store_result。*/
三、遍历和清理结果集
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)
/*检索结果集的下一行。在mysql_store_result()之后使用时,如果没有要检索的行,mysql_fetch_row()返回NULL。
在mysql_use_result()之后使用时,如果没有要检索的行或出现了错误,mysql_fetch_row()返回NULL。
返回值:
下一行的MYSQL_ROW结构。如果没有更多要检索的行或出现了错误,返回NULL。*/
void mysql_free_result(MYSQL_RES *result)
/*释放由mysql_store_result()、mysql_use_result()、mysql_list_dbs()等为结果集分配的内存。
完成对结果集的操作后,必须调用mysql_free_result()释放结果集使用的内存。*/
unsigned long *mysql_fetch_lengths(MYSQL_RES *result)
//返回结果集内当前行的列的长度。
//返回:无符号长整数的数组表示各列的大小(不包括任何终结NULL字符)。如果出现错误,返回NULL。
四、代码示例
#include <iostream>
#include <mysql.h>
#include <thread>
using namespace std;
int main()
{
//初始化mysql上下文
MYSQL mysql;
//单线程模式 mysql_init自动调用 mysql_library_init 线程不安全
mysql_init(&mysql);
const char *host = "127.0.0.1";
//const char *host = "192.168.0.203";
const char *user = "root";
const char *pass = "123456";
const char *db = "mysql"; //数据库名称
if (!mysql_real_connect(&mysql,host, user, pass, db, 3306, 0, 0))
{
cout << "mysql connect failed!" << mysql_error(&mysql) << endl;
}
else
{
cout << "mysql connect success!" << endl;
}
//user select * from user
// 1 执行SQL语句
const char *sql = "select * from user";
// mysql_real_query sql语句中可以包含二进制数据
// mysql_query sql语句中只能是字符串
// 0返回表示成功
int re = mysql_real_query(&mysql, sql, strlen(sql));
// Commands out of sync; you can't run this command now
// 执行sql语句后,必须获取结果集并且清理
// re = mysql_query(&mysql, sql);
if (re != 0)
{
cout << "mysql_real_query faied! "<< sql<<" " << mysql_error(&mysql) << endl;
}
else
{
cout << "mysql_real_query success! " << sql << endl;
}
//2 获取结果集
// mysql_use_result 不实际读取数据
//MYSQL_RES* result = mysql_use_result(&mysql);
//mysql_store_result 读取所有数据,注意缓存大小 MYSQL_OPT_MAX_ALLOWED_PACKET 默认 64M
MYSQL_RES* result = mysql_store_result(&mysql);
if (!result)
{
cout << "mysql_use_result faied! " << mysql_error(&mysql) << endl;
}
//3 遍历结果集
MYSQL_ROW row;
while (row = mysql_fetch_row(result))
{
unsigned long * lens = mysql_fetch_lengths(result);
cout<< lens[0] << "[" << row[0] << "," << row[1] << "]" << endl;
}
//清理结果集
mysql_free_result(result);
mysql_close(&mysql);
mysql_library_end();
std::cout << "Hello World!\n";
getchar();
}
四、表结构获取
代码,插入前面清理结果集
//获取表字段
MYSQL_FIELD *field = 0;
while (field = mysql_fetch_field(result))
{
cout << "key:" << field->name << endl;
}
//获取表字段数量
int fnum = mysql_num_fields(result);
//3 遍历结果集
MYSQL_ROW row;
while (row = mysql_fetch_row(result))
{
unsigned long * lens = mysql_fetch_lengths(result);
//cout<< lens[0] << "[" << row[0] << "," << row[1] << "]" << endl;
for (int i = 0; i < fnum; i++)
{
cout << mysql_fetch_field_direct(result, i)->name << ":";
if (row[i])
cout << row[i];
else
cout << "NULL";
cout<< ",";
}
cout <<"\n=========================================="<< endl;
}
五、表的创建、数据插入和修改
创建表的sql语句:
//1 创建表
sql = "CREATE TABLE IF NOT EXISTS `t_image` ( \
`id` int AUTO_INCREMENT,\
`name` varchar(1024),\
`path` varchar(2046),\
`size` int,\
PRIMARY KEY(`id`)\
) ";
int re = mysql_query(&mysql, sql.c_str());
if (re != 0)
{
cout << "mysql_query failed!" << mysql_error(&mysql) << endl;
}
添加数据:
数据添加的方式有两种:
//语法一:
insert into table_name [(column_name1,column_name2,...,column_namen)] values (value1,value2,...valuen)
//注意:
//1、字段列表的顺序可以不按照表中字段的顺序列出来,但对应值列表必须和字段名列表对应;
//2、对应值列表中的值如果是字符类型或日期类型,则需使用单引号引起来;
//3、如果没有字段列表,则值列表中值的顺序必须按照实际表中字段的默认顺序进行排列;
//语法二:
insert into to_table_name [(column_name1,column_name2,...,column_namen)]
//注意:
//insert子句中字段名列表的数目和数据类型必须和select子句中选择的字段列表的数目和数据类型相匹配。
修改数据:
update table_name set column1=value1, column2=value2……[where ……]
删除数据:
delete [from] table_name [where……]
完整代码:
#include <iostream>
#include <mysql.h>
#include <thread>
#include <string>
#include <sstream>
#include <map>
using namespace std;
int main()
{
//初始化mysql上下文
MYSQL mysql;
//单线程模式 mysql_init自动调用 mysql_library_init 线程不安全
mysql_init(&mysql);
const char *host = "127.0.0.1";
//const char *host = "192.168.0.203";
const char *user = "root";
const char *pass = "123456";
const char *db = "laoxiaketang"; //数据库名称
if (!mysql_real_connect(&mysql,host, user, pass, db, 3306, 0, 0))
{
cout << "mysql connect failed!" << mysql_error(&mysql) << endl;
}
else
{
cout << "mysql connect success!" << endl;
}
string sql = "";
//1 创建表
sql = "CREATE TABLE IF NOT EXISTS `t_image` ( \
`id` int AUTO_INCREMENT,\
`name` varchar(1024),\
`path` varchar(2046),\
`size` int,\
PRIMARY KEY(`id`)\
) ";
int re = mysql_query(&mysql, sql.c_str());
if (re != 0)
{
cout << "mysql_query failed!" << mysql_error(&mysql) << endl;
}
//清空数据,并恢复自增id从1开始
sql = "truncate t_image";
re = mysql_query(&mysql, sql.c_str());
if (re != 0)
{
cout << "mysql_query failed!" << mysql_error(&mysql) << endl;
}
//2 插入数据 CLIENT_MULTI_STATEMENTS
for (int i = 0; i < 10; i++)
{
//sql = "insert `t_image` (`name`,`path`,`size`) values('test.jpg','d:/img/test.jpg',10240)";
stringstream ss;
ss << "insert `t_image` (`name`,`path`,`size`)values('image";
ss << i << ".jpg','d:/img/', 10240)";
sql = ss.str();
re = mysql_query(&mysql, sql.c_str());
if (re == 0)
{
int count = mysql_affected_rows(&mysql);
cout << "insert mysql_affected_rows " << count << endl;
}
else
{
cout << "insert failed!" << mysql_error(&mysql) << endl;
}
}
//3 修改数据
//update t_image set `name`="test2.png",size=2000 where id=1
sql = "update t_image set `name`='test3.png',size=2000 where id=1";
re = mysql_query(&mysql, sql.c_str());
if (re == 0)
{
int count = mysql_affected_rows(&mysql);
cout << "update mysql_affected_rows " << count << endl;
}
else
{
cout << "update failed!" << mysql_error(&mysql) << endl;
}
//根据map自动生成 update sql语句
map<string, string> kv;
kv.insert(make_pair("name", "image_update001.png"));
kv.insert(make_pair("size", "5000"));
string where = " where id=2 ";
string tmp = "";
for (auto ptr = kv.begin(); ptr != kv.end(); ptr++)
{
tmp += "`";
tmp += ptr->first;
tmp += "`='";
tmp += ptr->second;
tmp += "',";
}
tmp += " id=id ";
sql = "update t_image set ";
sql += tmp;
sql += where;
re = mysql_query(&mysql, sql.c_str());
if (re == 0)
{
int count = mysql_affected_rows(&mysql);
cout << "update mysql_affected_rows " << count << endl;
}
else
{
cout << "update failed!" << mysql_error(&mysql) << endl;
}
//4 删除数据
sql = "delete from t_image where id=1";
re = mysql_query(&mysql, sql.c_str());
if (re == 0)
{
int count = mysql_affected_rows(&mysql);
cout << "delete mysql_affected_rows " << count << endl;
}
else
{
cout << "delete failed!" << mysql_error(&mysql) << endl;
}
//delete 不会实际删除空间,只做了标识
sql = "delete from t_image";
re = mysql_query(&mysql, sql.c_str());
if (re == 0)
{
int count = mysql_affected_rows(&mysql);
cout << "delete mysql_affected_rows " << count << endl;
}
else
{
cout << "delete failed!" << mysql_error(&mysql) << endl;
}
//实际清理了空间
sql = "OPTIMIZE TABLE t_image";
re = mysql_query(&mysql, sql.c_str());
mysql_close(&mysql);
mysql_library_end();
std::cout << "Mysql 8.0 API!\n";
getchar();
}
六、一次执行多条语句
mysql_real_connect(&mysql,host, user, pass, db, 3306, 0, CLIENT_MULTI_STATEMENTS)
//CLIENT_MULTI_STATEMENTS便是开启一次执行多条语句
代码实现:
#include <iostream>
#include <mysql.h>
#include <thread>
#include <string>
#include <sstream>
#include <map>
using namespace std;
int main()
{
//初始化mysql上下文
MYSQL mysql;
//单线程模式 mysql_init自动调用 mysql_library_init 线程不安全
mysql_init(&mysql);
const char *host = "127.0.0.1";
//const char *host = "192.168.0.203";
const char *user = "root";
const char *pass = "123456";
const char *db = "laoxiaketang"; //数据库名称
//CLIENT_MULTI_STATEMENTS 支持多条sql语句
if (!mysql_real_connect(&mysql,host, user, pass, db, 3306, 0, CLIENT_MULTI_STATEMENTS))
//if (!mysql_real_connect(&mysql, host, user, pass, db, 3306, 0, 0))
{
cout << "mysql connect failed!" << mysql_error(&mysql) << endl;
}
else
{
cout << "mysql connect success!" << endl;
}
string sql = "";
//1 创建表
sql = "CREATE TABLE IF NOT EXISTS `t_image` ( \
`id` int AUTO_INCREMENT,\
`name` varchar(1024),\
`path` varchar(2046),\
`size` int,\
PRIMARY KEY(`id`)\
) ;";
//清空数据,并恢复自增id从1开始
sql += "truncate t_image;";
//2 插入数据 CLIENT_MULTI_STATEMENTS
for (int i = 0; i < 100; i++)
{
//sql = "insert `t_image` (`name`,`path`,`size`) values('test.jpg','d:/img/test.jpg',10240)";
stringstream ss;
ss << "insert `t_image` (`name`,`path`,`size`)values('image";
ss << i << ".jpg','d:/img/', 10240);";
sql += ss.str();
}
//3 修改数据
//update t_image set `name`="test2.png",size=2000 where id=1
sql += "update t_image set `name`='test3.png',size=2000 where id=1;";
//4 删除数据
sql += "delete from t_image where id=1;";
//实际清理了空间
sql += "select * from t_image;";
//执行sql语句立刻返回,但语句并没有全部执行好,需要获取结果
//把sql整个发送给mysql server,server一条条执行,返回结果
int re = mysql_query(&mysql, sql.c_str());
if (re != 0)
{
cout << "mysql_query failed!" << mysql_error(&mysql) << endl;
}
//有多个返回结果
do
{
cout << "[result]";
MYSQL_RES * result = mysql_store_result(&mysql);
if (result) //SELECT
{
cout << "SELECT mysql_num_rows = " << mysql_num_rows(result) << endl;
mysql_free_result(result);
}
else // INSERT UPDATE DELETE CREATE DROP truncate
{
// SELECT 出错 有字段无结果
if (mysql_field_count(&mysql) > 0)
{
cout << "Not retrieve result! " <<mysql_error(&mysql)<< endl;
}
else //INSERT UPDATE DELETE CREATE DROP truncate
{
//等待服务器的处理结果
cout << mysql_affected_rows(&mysql) << " rows affected!" << endl;
}
}
}
//取下一条结果 0表示有结果
while (mysql_next_result(&mysql) == 0);
{
sql = "select * from t_image";
int re = mysql_query(&mysql, sql.c_str());
if (re != 0)
{
cout << "mysql_query failed!" << mysql_error(&mysql) << endl;
}
}
mysql_close(&mysql);
mysql_library_end();
std::cout << "Mysql 8.0 API!\n";
getchar();
}