C语言访问INFORMIX数据库 — 接口实现

1 简要概述

  INFORMIX数据库是IBM旗下的一款关系数据库,目前在金融行业占有不可替代的地位。使用C语言访问INFORMIX数据库的唯一方式是通过ESQL,其过程中有很多细节内容需要注意,但为了能够快速的理解各接口的流程,在此只给出各接口的基本框架。(注:ESQL语法在IBM帮助系统http://publib.boulder.ibm.com/infocenter/idshelp/v10/index.jsp?中有详尽的描述)


2 结构定义

/* 数据源配置信息 */
typedef struct
{
	char svrname[DB_SVR_NAME_MAX_LEN];   /* 服务名 */
	char usrname[DB_USR_NAME_MAX_LEN];   /* 用户名 */
	char passwd[DB_PWD_MAX_LEN];         /* 密码 */
}db_source_struct_t;

/* 数据库连接上下文信息 */
typedef struct
{
	char svrname[DB_SVR_NAME_MAX_LEN];         /* 服务名 */
	char cnname[DB_CONN_NAME_MAX_LEN];         /* 连接名 */

	/* 查询结果集 */
	ifx_sqlda_t *result;                       /* FETCH结果集 */
	int req_rows;                              /* 每次申请取的行数 */
	int rows;                                  /* 结果集中实际的行数 */
	int isalloced;                             /* 结果集空间是否被分配 0:未分配 1:已分配 */
	
	/* 结果转换 */
	char *convert;                             /* 结果转换空间 */
	size_t convert_size;                       /* 结果转换空间的大小 */

	int msglen;                                /* 存放查询数据的所有列的长度和 */
	size_t row_size;                           /* 存放了在C程序中的所有列(一行)的长度和 */
}db_ifx_cntx_t;

3 接口实现

3.1 连接数据库

/* 连接至INFORMIX数据库 */
int db_ifx_open(db_sourct_t *source, db_ifx_cntx_t **context)
{
    /* 连接数据库 */
    EXEC SQL CONNECT TO :svrname AS :cnname USER :usrname USING :passwd;

    /* 激活指定连接 */
    EXEC SQL SET CONNECTION :cnname;

    /* 开始事务 */
    EXEC SQL BEGIN WORK;
}

说明:
  1. 以上函数中的宿主变量svrname(服务名)、usrname(用户名)、passwd(登录密码)、cnname(连接名),这些变量的定义可参考:http://blog.csdn.net/royalapex/article/details/8201699
  2. 一个进程中可以有多个数据库连接,各数据库连接是通过连接名进行识别(区别、区分)的

3.2 断开连接

/* 断开与INFORMIX数据库的连接 */
int db_ifx_close(db_ifx_cntx_t *context)
{
    EXEC SQL COMMIT WORK;
    EXEC SQL DISCONNECT :cnname;
}

说明:
  1. 在连接数据库时,开启了事务,在断开连接时,应该关闭事务

3.3 提交事务

/* 提交事务 */
int db_ifx_commit(db_ifx_cntx_t *context)
{
    /* 提交事务 */
    EXEC SQL COMMIT WORK;

    /* 开始事务 */
    EXEC SQL BEGIN WORK;
}

说明:
  1. 断开连接时,关闭事务;故:提交事务后,需开启新的事务

3.4 回滚事务

/* 回滚事务 */
int db_ifx_rollback(void *context)
{
    /* 回滚事务 */
    EXEC SQL ROLLBACK WORK;

    /* 开始事务 */
    EXEC SQL BEGIN WORK;
}

说明:
  1. 断开连接时,关闭事务;故:回滚事务后,需开启新的事务

3.5 动态SQL:非查找语句

/* 执行非查询的动态SQL语句 */
int db_ifx_nquery(const char *sql, db_ifx_cntx_t *context)
{
EXEC SQL BEGIN DECLARE SECTION;
    char sql_stmt[SQL_STMT_MAX_LEN] = {0};
EXEC SQL END DECLARE SECTION;

    snprintf(sql_stmt, sizeof(sql_stmt), "%s", sql);

    /* 准备动态SQL语句 */
    EXEC SQL PREPARE NQUERY_SQLSTMT_ID FROM :sql_stmt;

    /* 执行:非查找SQL */
    EXEC SQL EXECUTE NQUERY_SQLSTMT_ID
}

说明:
  1. 执行动态非查询SQL的过程是:PREPARE动态语句, 再执行非查询SQL

3.6 动态SQL:查找语句

/* 执行一个动态查询sql(多行查询) */
int db_ifx_mquery(const char *sql, db_ifx_cntx_t *context)
{
EXEC SQL BEGIN DECLARE SECTION; 
	char sql_stmt[SQL_STMT_MAX_LEN];
EXEC SQL END DECLARE SECTION; 

	int ret = -1;
	ifx_sqlda_t *sqlda = NULL;
	
	snprintf(sql_stmt, sizeof(sql_stmt), "%s", sql);

	/* Step 1: PREPARE查询语句 */
 	EXEC SQL PREPARE QUERY_SQLSTMT_ID FROM :sql_stmt;
	
	/* Step 2: 使用describe函数完成两个功能:
		1. 为sqlda分配空间, 
		2. 获取语句信息,并存放在ifx_sqlda_t结构中 */
 	EXEC SQL DESCRIBE QUERY_SQLSTMT_ID INTO sqlda;

	do
	{
		/* Step 3: 初始化结果集 */
		ret = db_ifx_init_result(context, sqlda);
			
		/* Step 4: 声明和打开游标 */
	 	ret = db_ifx_declare(context);

	 	ret = db_ifx_copen(context);
		
		return sqlda->sqld;
	}while(0);

	db_ifx_free_sqlda(sqlda), sqlda = NULL;

	return -1;
}

说明:
  1. DESCRIBE: 为SQLDA分配空间,并获取语句信息,并存放在SQLDA结构中,信息包括:
      1) 列数

      2) 为struct sqlvar_struct结构分配sqld个空间,但未该结构体中的指针分配空间

      3) 数据类型

      4) 列长度等已初始化
  2. 关于db_ifx_sqlda_t的结构,可参考:http://blog.csdn.net/royalapex/article/details/8205654
  3. 关于db_ifx_sqlda_t的使用,可参考:http://blog.csdn.net/royalapex/article/details/8210965
  4. QUERY_SQLSTMT_ID:语句ID

3.7 定义游标

/* 声明游标 */
int db_ifx_declare(db_ifx_cntx_t *context)
{
 	EXEC SQL DECLARE QUERY_CURSOR_ID CURSOR FOR QUERY_SQLSTMT_ID;
}

说明:
  1. QUERY_CURSOR_ID:游标ID
  2. QUERY_SQLSTMT_ID:语句ID

3.8 打开游标

/* 打开游标 */
int db_ifx_copen(db_ifx_cntx_t *context)
{
 	EXEC SQL OPEN QUERY_CURSOR_ID;	
}

说明:
  1. QUERY_CURSOR_ID:游标ID

3.9 获取数据(FETCH)

/* 取出一个动态查询sql游标的一条记录  (返回值:0:未取到数据 1:取到一条 -1:失败) */
int db_ifx_fetch(db_ifx_cntx_t *context)
{
	ifx_sqlda_t *sqlda = (ifx_sqlda_t *)context->result;

	/* 1: 执行fetch操作,将数据存放在sqlda结构中 */
	EXEC SQL FETCH QUERY_CURSOR_ID USING DESCRIPTOR sqlda;
	if(SQLNOTFOUND == sqlca.sqlcode)
	{
		return 0;
	}
	else if(0 != sqlca.sqlcode)
	{
		return -1;
	}
	
	return 1;
}

说明:
  1. QUERY_CURSOR_ID:游标ID

4.10 关闭游标

/* 释放游标 */
int db_ifx_cclose(db_ifx_cntx_t *context) 
{ 
	/* 关闭游标 */
	EXEC SQL CLOSE QUERY_CURSOR_ID;

	EXEC SQL FREE QUERY_CURSOR_ID;
}

说明:
  1. QUERY_CURSOR_ID:游标ID 

你可能感兴趣的:(C语言访问INFORMIX数据库 — 接口实现)