当前位置:   article > 正文

Mysql 数据库APi 编程(c/c++)-1.1

Mysql 数据库APi 编程(c/c++)-1.1

日期时间类API函数

练习:熟悉上述预处理类工作模式,模拟精简一个将时间插入数据库的程序。将时间存入数据库有两种方式: 1. 使用SQL语句方式

2. 预处理环境句柄变量方式存入

提示:

MYSQL_TIME  ts; 浏览头文件 mysql_time.h 熟悉MYSQL_TIME结构体。

MYSQL_BIND  bind[3];

MYSQL_STMT  *stmt;

可直接使用SQL语句提前创建表test_table2,也可以使用mysql_query函数来创建。

create table test_table2 (date_field date, time_field time, timestamp_field timestamp);

char query[1024] = "INSERT INTO test_table2(date_field, time_field, timestamp_field) VALUES(?,?,?)";

stmt = mysql_stmt_init(mysql);

MYSQL_TIME 是一个结构体,使用typedef定义。位于mysql_time.h文件中。

API参考:refman-5.6-en.a4.pdf手册25.2.10. 日期和时间值的C API处理

多查询执行的C API函数

一次性执行多条SQL语句,包括select、drop、update、create等。 如:

mysql_query(mysql,"DROP TABLE IF EXISTS test_table;\

                 CREATE TABLE test_table(id INT);\

              INSERT INTO test_table VALUES(10);\

             UPDATE test_table SET id=20 WHERE id=10;\

             SELECT * FROM test_table;\

              DROP TABLE test_table");

文档:25.2.9. 多查询执行的C API处理。中文文档只有demo框架。查阅对应英文文档refman-5.6-en.a4.pdf。关键字Multiple 23.8.17

注意:打桩函数——函数接口

if (mysql_real_connect (mysql, host_name, user_name, password,

db_name, port_num, socket_name, CLIENT_MULTI_STATEMENTS) == NULL)

CLIENT_MULTI_STATEMENTS:客户端通知Server,将要发送多个SQL语句。

mysql_field_count(mysql):影响的行数。 如:

当select * from dept; 执行结束,提示:“5 rows in set” 表示影响了4行。

当Create一张表, 执行结束,提示:“Query OK, 0 rows affected (0.01 sec)”

当delete一行, 执行结束,提示:“Query OK, 1 row affected (0.00 sec)”

mysql_field_count函数调用后会将影响的行数保存到句柄 mysql 中。

将帮助文档中的demo导入程序,分析与我们之前掌握的API函数间的区别与联系:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "mysql.h"
  5. void process_result_set(MYSQL *mysql, MYSQL_RES *result)
  6. {
  7. int i, num;
  8. num = mysql_field_count(mysql);
  9. MYSQL_FIELD *fields = NULL;
  10. fields = mysql_fetch_fields(result);
  11. for (i = 0; i < num; i++) {
  12. printf("%10s\t", fields[i].name);
  13. }
  14. printf("\n");
  15. MYSQL_ROW row = NULL;
  16. while ((row = mysql_fetch_row(result))) {
  17. for (i = 0; i < num; i++) {
  18. printf("%10s\t", row[i]);
  19. }
  20. printf("\n");
  21. }
  22. }
  23. int main(void)
  24. {
  25. int ret = 0, status = 0;
  26. MYSQL_RES *result = NULL;
  27. MYSQL *mysql = mysql_init(NULL);
  28. if (mysql == NULL) {
  29. //unsigned int mysql_errno(MYSQL *mysql)
  30. ret = mysql_errno(mysql);
  31. printf("mysql_init err:%d\n", ret);
  32. return ret;
  33. }
  34. mysql = mysql_real_connect(mysql, "localhost", "root", "123456", "mydb61", 0, NULL, CLIENT_MULTI_STATEMENTS);
  35. if (mysql == NULL) {
  36. ret = mysql_errno(mysql);
  37. printf("mysql_init err:%d\n", ret);
  38. return ret;
  39. }
  40. /以下为demo源码//
  41. /* execute multiple statements */
  42. status = mysql_query(mysql,"DROP TABLE IF EXISTS test_table;\
  43. CREATE TABLE test_table(id INT);\
  44. INSERT INTO test_table VALUES(10);\
  45. UPDATE test_table SET id=20 WHERE id=10;\
  46. SELECT * FROM test_table;");
  47. DROP TABLE test_table
  48. if (status)
  49. {
  50. printf("Could not execute statement(s)");
  51. mysql_close(mysql);
  52. exit(0);
  53. }
  54. /* process each statement result */
  55. do {
  56. /* did current statement return data? */
  57. result = mysql_store_result(mysql);
  58. if (result)
  59. {
  60. /* yes; process rows and free the result set */
  61. process_result_set(mysql, result);
  62. mysql_free_result(result);
  63. }
  64. else /* no result set or error */
  65. {
  66. if (mysql_field_count(mysql) == 0)
  67. {
  68. printf("%lld rows affected\n",
  69. mysql_affected_rows(mysql));
  70. }
  71. else /* some error occurred */
  72. {
  73. printf("Could not retrieve result set\n");
  74. break;
  75. } }
  76. /* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
  77. if ((status = mysql_next_result(mysql)) > 0)
  78. printf("Could not execute statement\n");
  79. printf("------------status: %d\n", status);
  80. } while (status == 0);
  81. mysql_close(mysql);
  82. return 0;
  83. }

process_result_set函数是文档中给我们预留的打桩函数,需要我们在使用的过程中,自己实现它。

函数实现就是借助mysql和result两个参数打印一条sql语句查询到的结果集到屏幕。

可以直接使用mysq_tool.c中if (strncmp(sqlbuf, "select", 6) == 0 || strncmp(sqlbuf, "SELECT", 6) == 0)内的代码。“获取结果集”片段可以删除。“释放结果集”片段可以删除。API示例中含有该部分内容。

常见错误:在process_result_set函数实现中,不要使用mysql_store_result(mysql)再次获取结果集, 该result已经在API函数接口传入,直接使用参数result即可。否则会出现【段错误】。

MySQL中的事务

测试MySQL中事务的特性。

MySQL的事务的默认自动提交的,每执行一个sql语句都自动commit

Oracle的事务是自动打开的(以你执行的一条DML语句为标志),但每次执行需要手动commit

在程序中设置autocommit修改MySQL事务的属性。

set autocommit = 0 禁止自动提交

set autocommit = 1 开启自动提交MySQL中InnoDB引擎才支持事务默认自动提交机制。MYISAM引擎不支持。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "mysql.h"
  5. #define SET_TRAN "SET AUTOCOMMIT=0"   //手动commit
  6. #define UNSET_TRAN "SET AUTOCOMMIT=1" //自动commit
  7. //设置事务为手动提交
  8. int mysql_OperationTran(MYSQL *mysql)  
  9. {
  10. //--开启事务
  11. int ret = mysql_query(mysql, "start transaction");  
  12. if (ret != 0) {
  13. printf("mysql_OperationTran query start err: %s\n", mysql_error(mysql));
  14. return ret;
  15. }
  16. //--设置事务为手动提交
  17. ret = mysql_query(mysql, SET_TRAN);
  18. if (ret != 0) {
  19. printf("mysql_OperationTran query set err: %s\n", mysql_error(mysql));
  20. return ret;
  21. }
  22. return ret;
  23. }
  24. //设置事务为自动提交
  25. int mysql_AutoTran(MYSQL *mysql)
  26. {
  27. //--开启事务
  28. int ret = mysql_query(mysql, "start transaction");  
  29. if (ret != 0) {
  30. printf("mysql_AutoTran query start err: %s\n", mysql_error(mysql));
  31. return ret;
  32. }
  33. //--设置事务为自动提交
  34. ret = mysql_query(mysql, UNSET_TRAN);
  35. if (ret != 0) {
  36. printf("mysql_AutoTran query set err: %s\n", mysql_error(mysql));
  37. return ret;
  38. }
  39. return ret;
  40. }
  41. //执行commit,手动提交事务
  42. int mysql_Commit(MYSQL *mysql)
  43. {
  44. int ret = mysql_query(mysql, "COMMIT");
  45. if (ret != 0) {
  46. printf("commit err: %s\n", mysql_error(mysql));
  47. return ret;
  48. }
  49. return ret;
  50. }
  51. //执行rollback,回滚事务
  52. int mysql_Rollback(MYSQL *mysql)
  53. {
  54. int ret = mysql_query(mysql, "ROLLBACK");
  55. if (ret != 0) {
  56. printf("rollback err: %s\n", mysql_error(mysql));
  57. return ret;
  58. }
  59. return ret;
  60. }
  61. #define DROP_SAMPLE_TABLE "DROP TABLE IF EXISTS test_table"
  62. #define CREATE_SAMPLE_TABLE "CREATE TABLE test_table(col1 INT,\
  63.                                                  col2 VARCHAR(10),\
  64.                                                  col3 VARCHAR(10))"
  65.                                                                                        
  66. #define sql01 "INSERT INTO test_table(col1,col2,col3) VALUES(10, 'AAA', 'A1')"
  67. #define sql02 "INSERT INTO test_table(col1,col2,col3) VALUES(20, 'BBB', 'B2')"
  68. #define sql03 "INSERT INTO test_table(col1,col2,col3) VALUES(30, 'CCC', 'C3')"
  69. #define sql04 "INSERT INTO test_table(col1,col2,col3) VALUES(40, 'DDD', 'D4')"
  70. int main(void)
  71. {
  72. int ret = 0;
  73. MYSQL *mysql = mysql_init(NULL);
  74. mysql = mysql_real_connect(mysql, "localhost", "root", "123456", "mydb2", 0, NULL, 0);
  75. if (mysql == NULL) {
  76. ret = mysql_errno(mysql);
  77. printf("func mysql_real_connect() err:%d\n", ret);
  78. return ret;
  79. }
  80. printf(" --- connect ok......\n");
  81. if (mysql_query(mysql, DROP_SAMPLE_TABLE)) {
  82.   fprintf(stderr, " DROP TABLE failed\n");
  83.   fprintf(stderr, " %s\n", mysql_error(mysql));
  84.   exit(0);
  85. }
  86. if (mysql_query(mysql, CREATE_SAMPLE_TABLE)) {
  87.   fprintf(stderr, " CREATE TABLE failed\n");
  88.   fprintf(stderr, " %s\n", mysql_error(mysql));
  89.   exit(0);
  90. }
  91. ret = mysql_OperationTran(mysql); //开启事务,并修改事务属性为手动commit
  92. if (ret != 0) {
  93. printf("mysql_OperationTran() err:%d\n", ret);
  94. return ret;
  95. }
  96. ret = mysql_query(mysql, sql01); //向表中插入第一行数据 ‘AAA’
  97. if (ret != 0) {
  98. printf("mysql_query() err:%d\n", ret); return ret;
  99. }
  100. ret = mysql_query(mysql, sql02); //向表中插入第二行数据 ‘BBB’
  101. if (ret != 0) {
  102. printf("mysql_query() err:%d\n", ret);
  103. return ret;
  104. }
  105. ret = mysql_Commit(mysql); //手动提交事务
  106. if (ret != 0) {
  107. printf("mysql_Commit() err:%d\n", ret);
  108. return ret;
  109. }
  110. ret = mysql_AutoTran(mysql); // =再次= 修改事务属性为【自动】commit
  111. if (ret != 0) {
  112. printf("mysql_OperationTran() err:%d\n", ret);
  113. return ret;
  114. }
  115. ret = mysql_OperationTran(mysql); // =再次= 修改事务属性为【手动】commit
  116. if (ret != 0) {
  117. printf("mysql_OperationTran() err:%d\n", ret);
  118. return ret;
  119. }
  120. ret = mysql_query(mysql, sql03); //向表中插入第三行数据 ‘CCC’
  121. if (ret != 0) {
  122. printf("mysql_query() err:%d\n", ret);
  123. return ret;
  124. }
  125. ret = mysql_query(mysql, sql04); //向表中插入第四行数据 ‘DDD’
  126. if (ret != 0) {
  127. printf("mysql_query() err:%d\n", ret);
  128. return ret;
  129. }
  130. ret = mysql_Rollback(mysql); //直接rollback操作
  131. if (ret != 0) {
  132. printf("mysql_Rollback() err:%d\n", ret);
  133. return ret;
  134. }
  135. //rollback操作是否能回退掉CCC、DDD的值,取决于事务属性。
  136. mysql_close(mysql);
  137. return 0;
  138. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/614157
推荐阅读
相关标签
  

闽ICP备14008679号