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函数间的区别与联系:

#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中事务的特性。

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;

}

  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值