赞
踩
练习:熟悉上述预处理类工作模式,模拟精简一个将时间插入数据库的程序。将时间存入数据库有两种方式: 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函数间的区别与联系:
- #include <stdio.h>
-
- #include <stdlib.h>
-
- #include <string.h>
-
- #include "mysql.h"
-
- void process_result_set(MYSQL *mysql, MYSQL_RES *result)
-
- {
-
- int i, num;
-
- num = mysql_field_count(mysql);
-
-
-
- MYSQL_FIELD *fields = NULL;
-
- fields = mysql_fetch_fields(result);
-
- for (i = 0; i < num; i++) {
-
- printf("%10s\t", fields[i].name);
-
- }
-
- printf("\n");
-
-
-
- MYSQL_ROW row = NULL;
-
- while ((row = mysql_fetch_row(result))) {
-
- for (i = 0; i < num; i++) {
-
- printf("%10s\t", row[i]);
-
- }
-
- printf("\n");
-
- }
-
- }
-
-
-
- int main(void)
-
- {
-
- int ret = 0, status = 0;
-
-
-
- MYSQL_RES *result = NULL;
-
-
-
- MYSQL *mysql = mysql_init(NULL);
-
- if (mysql == NULL) {
-
- //unsigned int mysql_errno(MYSQL *mysql)
-
- ret = mysql_errno(mysql);
-
- printf("mysql_init err:%d\n", ret);
-
- return ret;
-
- }
-
-
-
- mysql = mysql_real_connect(mysql, "localhost", "root", "123456", "mydb61", 0, NULL, CLIENT_MULTI_STATEMENTS);
-
- if (mysql == NULL) {
-
- ret = mysql_errno(mysql);
-
- printf("mysql_init err:%d\n", ret);
-
- return ret;
-
- }
-
- /以下为demo源码//
-
- /* execute multiple statements */
-
- status = 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
-
- if (status)
-
- {
-
- printf("Could not execute statement(s)");
-
- mysql_close(mysql);
-
- exit(0);
-
- }
-
- /* process each statement result */
-
- do {
-
- /* did current statement return data? */
-
- result = mysql_store_result(mysql);
-
- if (result)
-
- {
-
- /* yes; process rows and free the result set */
-
- process_result_set(mysql, result);
-
- mysql_free_result(result);
-
- }
-
- else /* no result set or error */
-
- {
-
- if (mysql_field_count(mysql) == 0)
-
- {
-
- printf("%lld rows affected\n",
-
- mysql_affected_rows(mysql));
-
- }
-
- else /* some error occurred */
-
- {
-
- printf("Could not retrieve result set\n");
-
- break;
-
- } }
-
-
-
- /* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
-
- if ((status = mysql_next_result(mysql)) > 0)
-
- printf("Could not execute statement\n");
-
-
-
- printf("------------status: %d\n", status);
-
-
-
- } while (status == 0);
-
- mysql_close(mysql);
-
-
-
- return 0;
-
- }
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的事务的默认自动提交的,每执行一个sql语句都自动commit
Oracle的事务是自动打开的(以你执行的一条DML语句为标志),但每次执行需要手动commit
在程序中设置autocommit修改MySQL事务的属性。
set autocommit = 0 禁止自动提交
set autocommit = 1 开启自动提交MySQL中InnoDB引擎才支持事务默认自动提交机制。MYISAM引擎不支持。
- #include <stdio.h>
-
- #include <stdlib.h>
-
- #include <string.h>
-
- #include "mysql.h"
-
- #define SET_TRAN "SET AUTOCOMMIT=0" //手动commit
-
- #define UNSET_TRAN "SET AUTOCOMMIT=1" //自动commit
-
- //设置事务为手动提交
-
- int mysql_OperationTran(MYSQL *mysql)
-
- {
-
- //--开启事务
-
- int ret = mysql_query(mysql, "start transaction");
-
- if (ret != 0) {
-
- printf("mysql_OperationTran query start err: %s\n", mysql_error(mysql));
-
- return ret;
-
- }
-
-
-
- //--设置事务为手动提交
-
- ret = mysql_query(mysql, SET_TRAN);
-
- if (ret != 0) {
-
- printf("mysql_OperationTran query set err: %s\n", mysql_error(mysql));
-
- return ret;
-
- }
-
- return ret;
-
- }
-
- //设置事务为自动提交
-
- int mysql_AutoTran(MYSQL *mysql)
-
- {
-
- //--开启事务
-
- int ret = mysql_query(mysql, "start transaction");
-
- if (ret != 0) {
-
- printf("mysql_AutoTran query start err: %s\n", mysql_error(mysql));
-
- return ret;
-
- }
-
- //--设置事务为自动提交
-
- ret = mysql_query(mysql, UNSET_TRAN);
-
- if (ret != 0) {
-
- printf("mysql_AutoTran query set err: %s\n", mysql_error(mysql));
-
- return ret;
-
- }
-
- return ret;
-
- }
-
- //执行commit,手动提交事务
-
- int mysql_Commit(MYSQL *mysql)
-
- {
-
- int ret = mysql_query(mysql, "COMMIT");
-
- if (ret != 0) {
-
- printf("commit err: %s\n", mysql_error(mysql));
-
- return ret;
-
- }
-
- return ret;
-
- }
-
-
-
- //执行rollback,回滚事务
-
- int mysql_Rollback(MYSQL *mysql)
-
- {
-
- int ret = mysql_query(mysql, "ROLLBACK");
-
- if (ret != 0) {
-
- printf("rollback err: %s\n", mysql_error(mysql));
-
- return ret;
-
- }
-
- return ret;
-
- }
-
- #define DROP_SAMPLE_TABLE "DROP TABLE IF EXISTS test_table"
-
- #define CREATE_SAMPLE_TABLE "CREATE TABLE test_table(col1 INT,\
- col2 VARCHAR(10),\
- col3 VARCHAR(10))"
-
-
-
- #define sql01 "INSERT INTO test_table(col1,col2,col3) VALUES(10, 'AAA', 'A1')"
-
- #define sql02 "INSERT INTO test_table(col1,col2,col3) VALUES(20, 'BBB', 'B2')"
-
- #define sql03 "INSERT INTO test_table(col1,col2,col3) VALUES(30, 'CCC', 'C3')"
-
- #define sql04 "INSERT INTO test_table(col1,col2,col3) VALUES(40, 'DDD', 'D4')"
-
-
-
- int main(void)
-
- {
-
- int ret = 0;
-
- MYSQL *mysql = mysql_init(NULL);
-
-
-
- mysql = mysql_real_connect(mysql, "localhost", "root", "123456", "mydb2", 0, NULL, 0);
-
- if (mysql == NULL) {
-
- ret = mysql_errno(mysql);
-
- printf("func mysql_real_connect() err:%d\n", ret);
-
- return ret;
-
- }
-
- printf(" --- connect ok......\n");
-
-
-
- if (mysql_query(mysql, DROP_SAMPLE_TABLE)) {
-
- fprintf(stderr, " DROP TABLE failed\n");
-
- fprintf(stderr, " %s\n", mysql_error(mysql));
-
- exit(0);
-
- }
-
- if (mysql_query(mysql, CREATE_SAMPLE_TABLE)) {
-
- fprintf(stderr, " CREATE TABLE failed\n");
-
- fprintf(stderr, " %s\n", mysql_error(mysql));
-
- exit(0);
-
- }
-
-
-
- ret = mysql_OperationTran(mysql); //开启事务,并修改事务属性为手动commit
-
- if (ret != 0) {
-
- printf("mysql_OperationTran() err:%d\n", ret);
-
- return ret;
-
- }
-
-
-
- ret = mysql_query(mysql, sql01); //向表中插入第一行数据 ‘AAA’
-
- if (ret != 0) {
-
- printf("mysql_query() err:%d\n", ret); return ret;
-
- }
-
- ret = mysql_query(mysql, sql02); //向表中插入第二行数据 ‘BBB’
-
- if (ret != 0) {
-
- printf("mysql_query() err:%d\n", ret);
-
- return ret;
-
- }
-
- ret = mysql_Commit(mysql); //手动提交事务
-
- if (ret != 0) {
-
- printf("mysql_Commit() err:%d\n", ret);
-
- return ret;
-
- }
-
-
-
- ret = mysql_AutoTran(mysql); // =再次= 修改事务属性为【自动】commit
-
- if (ret != 0) {
-
- printf("mysql_OperationTran() err:%d\n", ret);
-
- return ret;
-
- }
-
- ret = mysql_OperationTran(mysql); // =再次= 修改事务属性为【手动】commit
-
- if (ret != 0) {
-
- printf("mysql_OperationTran() err:%d\n", ret);
-
- return ret;
-
- }
-
- ret = mysql_query(mysql, sql03); //向表中插入第三行数据 ‘CCC’
-
- if (ret != 0) {
-
- printf("mysql_query() err:%d\n", ret);
-
- return ret;
-
- }
-
- ret = mysql_query(mysql, sql04); //向表中插入第四行数据 ‘DDD’
-
- if (ret != 0) {
-
- printf("mysql_query() err:%d\n", ret);
-
- return ret;
-
- }
-
- ret = mysql_Rollback(mysql); //直接rollback操作
-
- if (ret != 0) {
-
- printf("mysql_Rollback() err:%d\n", ret);
-
- return ret;
-
- }
-
- //rollback操作是否能回退掉CCC、DDD的值,取决于事务属性。
-
- mysql_close(mysql);
-
- return 0;
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。