C++连接MySQL数据库
文章目录
- C++连接MySQL数据库
- 1. MySQL常用API函数
- mysql_init和mysql_close
- mysql_real_connect
- mysql_query
- mysql_real_query/mysql_store_result/mysql_fetch_row
- mysql_affected_rows
- mysql_field_count
- mysql_fetch_fields
- mysql_fetch_lengths
- mysql_free_result
- mysql_next_result
- mysql_insert_id
- mysql_real_escape_string
- 2. 实例
官方API接口说明
1. MySQL常用API函数
| 函数签名 | 解释 |
|---|---|
| mysql_affected_rows() | 返回被最新的UPDATE, DELETE或INSERT查询影响的行数 |
| void mysql_close(MYSQL *sock) | 关闭一个服务器连接 |
| mysql_connect() | 连接一个MySQL服务器。该函数不推荐;使用mysql_real_connect()代替 |
| mysql_change_user() | 改变在一个打开的连接上的用户和数据库 |
| mysql_create_db() | 创建一个数据库。该函数不推荐;而使用SQL命令CREATE DATABASE |
| mysql_data_seek() | 在一个查询结果集合中搜寻一任意行 |
| mysql_debug() | 用给定字符串做一个DBUG_PUSH |
| mysql_drop_db() | 销毁一个数据库。该函数不推荐;而使用SQL命令DROP DATABASE |
| mysql_dump_debug_info() | 让服务器将调试信息写入日志文件 |
| mysql_eof() | 确定是否已经读到一个结果集合的最后一行。这功能被反对; mysql_errno()或mysql_error()可以相反被使用。 |
| mysql_errno() | 返回最近被调用的MySQL函数的出错编号 |
| mysql_error() | 返回最近被调用的MySQL函数的出错消息 |
| mysql_escape_string() | 用在SQL语句中的字符串的转义特殊字符 |
| mysql_fetch_field() | 返回下一个表字段的类型 |
| mysql_fetch_field_direct () | 返回一个表字段的类型,给出一个字段编号 |
| mysql_fetch_fields() | 返回一个所有字段结构的数组 |
| mysql_fetch_lengths() | 返回当前行中所有列的长度 |
| mysql_fetch_row() | 从结果集合中取得下一行 |
| mysql_field_seek() | 把列光标放在一个指定的列上 |
| mysql_field_count() | 返回最近查询的结果列的数量 |
| mysql_field_tell() | 返回用于最后一个mysql_fetch_field()的字段光标的位置 |
| mysql_free_result() | 释放一个结果集合使用的内存 |
| mysql_get_client_info() | 返回客户版本信息 |
| mysql_get_host_info() | 返回一个描述连接的字符串 |
| mysql_get_proto_info() | 返回连接使用的协议版本 |
| mysql_get_server_info() | 返回服务器版本号 |
| mysql_info() | 返回关于最近执行得查询的信息 |
| MYSQL * mysql_init(MYSQL *mysql); | 获得或初始化一个MYSQL结构 |
| mysql_insert_id() | 返回有前一个查询为一个AUTO_INCREMENT列生成的ID |
| mysql_kill() | 杀死一个给定的线程 |
| mysql_list_dbs() | 返回匹配一个简单的正则表达式的数据库名 |
| mysql_list_fields() | 返回匹配一个简单的正则表达式的列名 |
| mysql_list_processes() | 返回当前服务器线程的一张表 |
| mysql_list_tables() | 返回匹配一个简单的正则表达式的表名 |
| mysql_num_fields() | 返回一个结果集合中的列的数量 |
| mysql_num_rows() | 返回一个结果集合中的行的数量 |
| mysql_options() | 设置对mysql_connect()的连接选项 |
| mysql_ping() | 检查对服务器的连接是否正在工作,必要时重新连接 |
| mysql_query() | 执行指定为一个空结尾的字符串的SQL查询 |
| mysql_real_connect() | 连接一个MySQL服务器 |
| mysql_real_query() | 执行指定为带计数的字符串的SQL查询 |
| mysql_reload() | 告诉服务器重装授权表 |
| mysql_row_seek() | 搜索在结果集合中的行,使用从mysql_row_tell()返回的值 |
| mysql_row_tell() | 返回行光标位置 |
| mysql_select_db() | 连接一个数据库 |
| mysql_shutdown() | 关掉数据库服务器 |
| mysql_stat() | 返回作为字符串的服务器状态 |
| mysql_store_result() | 检索一个完整的结果集合给客户 |
| mysql_thread_id() | 返回当前线程的ID |
| mysql_use_result() | 初始化一个一行一行地结果集合的检索 |
mysql_init和mysql_close
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | MYSQL *mysql_init(MYSQL *mysql); // 初始化一个MYSQL 连接的实例对象 void mysql_close(MYSQL *sock); // 释放一个MYSQL 连接实例 这个函数有两种用法: 1. 参数传NULL 值。 // 这种情况很显然,是mysql_init() 函数内部申请了一片内存,然后返回了首地址。 MYSQL *ms_conn = mysql_init(NULL); // 用完记得要释放 mysql_close(ms_conn), ms_conn = NULL; 2. 参数传对象地址。 // 这种情况就是使用栈内存,mysql_init() 函数显然不应该给分配堆内存。 MYSQL ms_eg; MYSQL *ms_conn = mysql_init(&ms_eg); // 用完记得要释放 mysql_close(ms_conn), ms_conn = NULL; 这个函数用来分配或者初始化一个MYSQL对象,用于连接mysql服务端。如果你传入的参数是NULL指针,它将自动为你分配一个MYSQL对象,如果这个MYSQL对象是它自动分配的,那么在调用mysql_close的时候,会释放这个对象。那么,这就有可能出现一个问题,就是,当你主动调用mysql_close之后,可能因为某些原因,又调用一次mysql_close,第二次调用,有可能因为mysql已经是野指针导致程序崩溃。另外,在我的实际运用过程中,有出现一些api调用过程中出错时,自动调用了mysql_close的情况。由于这种自动调用不会被程序感知,因此程序主动close的时候会导致崩溃。为了安全起见,建议不要让mysql_init api自动创建MYSQL对象,而由自己管理这个对象,并且传入地址让它完成初始化,这样,即使你多次调用close函数,也不会出现程序崩溃的现象。 |
mysql_real_connect
1 2 3 4 5 6 7 8 | MYSQL *STDCALL 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 clientflag); 连接一个MySQL服务器 |
mysql_query
1 2 | int STDCALL mysql_query(MYSQL *mysql, const char *q); 执行指定为一个空结尾的字符串的SQL查询 |
mysql_real_query/mysql_store_result/mysql_fetch_row
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | int mysql_real_query(MYSQL *mysql, const char *q, unsigned long length); 说明:执行SQL 参数1:已初始化的MYSQL 实例; 参数2:SQL 语句; 参数3:SQL 语句字符数。 Zero for success. Nonzero if an error occurred. Error: CR_COMMANDS_OUT_OF_SYNC Commands were executed in an improper order. CR_SERVER_GONE_ERROR The MySQL server has gone away. CR_SERVER_LOST The connection to the server was lost during the query. CR_UNKNOWN_ERROR An unknown error occurred. 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。 |
mysql_affected_rows
1 2 3 | my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql); mysql_affected_rows() 取得前一次 MySQL 操作所影响的记录行数。mysql_num_rows()仅对 SELECT 语句有效,要取得被 INSERT,UPDATE 或者 DE mysql_affected_rows返回被最新的UPDATE, DELETE或INSERT查询影响的行数 |
mysql_field_count
1 2 | unsigned int STDCALL mysql_field_count(MYSQL *mysql); 返回最近查询的结果列的数量 |
mysql_fetch_fields
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result); 返回一个所有字段结构的数组 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; |
mysql_fetch_lengths
1 2 | unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result); 返回当前行中所有列的长度 |
mysql_free_result
1 2 | void STDCALL mysql_free_result(MYSQL_RES *result); 释放一个结果集合使用的内存 |
mysql_next_result
1 2 3 4 5 6 | int STDCALL mysql_next_result(MYSQL *mysql); mysql_next_result 在存储过程中,有可能返回多个结果集,mysql_store_result用来处理当前,mysql_next_result用来处理下一个. Return Value Description 0 Successful and there are more results -1 Successful and there are no more results >0 An error occurred |
mysql_insert_id
1 2 | my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql); 返回有前一个查询为一个AUTO_INCREMENT列生成的ID |
mysql_real_escape_string
1 2 3 4 5 6 7 8 9 | unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, unsigned long length); 该函数用于创建可在SQL语句中使用的合法SQL字符串 按照连接的当前字符集,将“from”中的字符串编码为转义SQL字符串。将结果置于“to”中,并添加1个终结用NULL字节。编码的字符为NUL (ASCII 0)、‘\\n’、‘\\r’、‘\\’、‘'’、‘"’、以及Control-Z(请参见9.1节,“文字值”)。(严格地讲,MySQL仅需要反斜杠和引号字符,用于引用转义查询中的字符串。该函数能引用其他字符,从而使得它们在日志文件中具有更好的可读性)。 “from”指向的字符串必须是长度字节“long”。必须为“to”缓冲区分配至少length*2+1字节。在最坏的情况下,每个字符或许需要使用2个字节进行编码,而且还需要终结Null字节。当mysql_real_escape_string()返回时,“to”的内容是由Null终结的字符串。返回值是编码字符串的长度,不包括终结用Null字符。 如果需要更改连接的字符集,应使用mysql_set_character_set()函数,而不是执行SET NAMES (或SET CHARACTER SET)语句。mysql_set_character_set()的工作方式类似于SET NAMES,但它还能影响mysql_real_escape_string()所使用的字符集,而SET NAMES则不能 |
2. 实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | #include<iostream> #include<Windows.h> #include<WinSock.h> #include<mysql.h> using namespace std; #pragma comment(lib,"libmysql.lib") #pragma comment(lib,"wsock32.lib") MYSQL *mysql = new MYSQL; //mysql连接 MYSQL_FIELD *fd; //字段列数组 char field[32][32]; //存字段名二维数组 MYSQL_RES *res; //这个结构代表返回行的一个查询结果集 MYSQL_ROW column; //一个行数据的类型安全(type-safe)的表示,表示数据行的列, typedef char **MYSQL_ROW; char query[256]; //查询语句 bool ConnectDatabase() { //初始化mysql mysql_init(mysql); //返回false则连接失败,返回true则连接成功 if (!(mysql_real_connect(mysql, "localhost", "root", "199618", "chatinfo", 0, NULL, 0))) //中间分别是主机,用户名,密码,数据库名,端口号(可以写默认0或者3306等),可以先写成参数再传进去 { printf("Error connecting to database:%s\n", mysql_error(mysql)); return false; } else { printf("Connected...\n"); return true; } return true; } bool QueryDatabase(std::string sql) { sprintf_s(query, sql.c_str()); //执行查询语句,这里是查询所有,user是表名,不用加引号,用strcpy也可以 mysql_query(mysql, "set names utf8"); //设置编码格式(SET NAMES GBK也行),否则cmd下中文乱码 //返回0 查询成功,返回1查询失败 if (mysql_query(mysql, query)) //执行SQL语句 { printf("Query failed (%s)\n", mysql_error(mysql)); return false; } else { printf("query success\n"); } //获取结果集 if (!(res = mysql_store_result(mysql))) //获得sql语句结束后返回的结果集 { printf("Couldn't get result from %s\n", mysql_error(mysql)); return false; } //打印数据行列数 int s32_Column = mysql_num_fields(res); int s32_Rows = mysql_affected_rows(mysql); //获取字段的信息 char *str_field[32]; //定义一个字符串数组存储字段信息 for (int i = 0; i < s32_Column; i++) //在已知字段数量的情况下获取字段名 { str_field[i] = mysql_fetch_field(res)->name; printf("%10s\t", str_field[i]); } printf("\n"); //打印获取的数据 while (column = mysql_fetch_row(res)) //在已知字段数量情况下,获取并打印下一行 { for (int i = 0; i < s32_Column; i++) { printf("%10s\t", column[i]); } printf("\n"); } return true; } int main() { if (ConnectDatabase()) { std::string sql = "select * from user"; QueryDatabase(sql); sql = "delete from user where char_id = 2"; QueryDatabase(sql); sql = "INSERT INTO User\ (nickname, birthday, address, gender)\ VALUES\ ('CXX', '1998', 'shanghai', 0); "; QueryDatabase(sql); sql = "Update user set nickname = 'Java' where birthday = 1998"; QueryDatabase(sql); } system("pause"); return 0; } |
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 | Connected... query success char_id nickname birthday address gender 1 Python 19970118 shenzhen 1 3 Rust 19890118 shanghai 0 4 Java 1998 shanghai 0 Query failed (Unknown column 'Lua' in 'where clause') query success Couldn't get result from query success Couldn't get result from 请按任意键继续. . . |
对于成功检索了数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN、CHECK TABLE等),必须调用mysql_store_result()或mysql_use_result()获得查询结果.在DELETE FROM、 UPDATE和INSERT INTO中调用mysql_store_result返回NULL;