ACI编程基础
ACI 用户编程的基本流程如下:
- 初始化神通 ACI 接口的运行环境
- 分配环境句柄、语句句柄、服务器句柄、会话句柄等数据结构
- 建立与神通数据库的连接以及创建用户会话
- 通过 SQL 语句与神通数据库服务器交互,然后对获取的数据进行处理
- 结束用户会话,断开 ACI 接口与神通数据库的连接
- 释放在程序中所分配的各类句柄和资源
使用的函数
- 准备 SQL 语句调用函数ACIStmtPrepare
- 在 SQL 语句中绑定需要输入到 SQL 语句中的变量
对于 DML 语句来说,由于它带有输入变量,我们可以通过调用一个或者多个函数CIBindByPos /ACIBindByPos2 / ACIBindByName / ACIBindByName2 等把输入变量的地址绑定在 DML 语句中的占位符中; - 执行 SQL 语句
调用ACIStmtExecute 函数。对于 DDL 语句到这一步就完成了一个语句的执行 - 描述 SQL 中的输出的数据
如果有必要的话,我们可以调用函数ACIParamGet 与ACIAttrGet 来获取我们所读取的记录的字段个数、字段的数据类型以及字段数据定义的最大长度。 - 定义输出变量
对于 DQL(Data Query Language) 语句,即 SELECT 的查询语句,需要定义一定数量的变量用来接受所选择列的数据。我们可以调用ACIDefineByPos 函数等来完成这个任务。也就建立 SQL 语句所返回的数据与应用程序中变量的关系。 - 获取数据
我们可以调用函数ACIStmtFetch 来把用 SELECT 选中的记录的数据赋予应用程序中的变量。过程以及过程中调用到的函数如所示。
编程例子
/*
本例中的 SQL 语句为 SELECT 语句,假设后台数据库中存在表名为 mt_t 表
建表语句
create table mt_t(id number(10),col1 number(10));
insert into mt_t values(10,100);
insert into mt_t values(11,1000);
*/
#include <aci.h>
/* 句柄分配 */
ACIEnv *m_penv = NULL; /* 环境句柄 */
ACIError *m_perr = NULL; /* 错误句柄 */
ACIServer *m_psrv = NULL; /* 服务器句柄 */
ACISvcCtx *m_psvc = NULL; /* 服务上下文句柄 */
ACISession *m_pses = NULL; /* 会话句柄 */
ACIStmt *m_pstmt = NULL; /* 语句句柄 */
ACIBind *m_bnd = NULL; /* 绑定句柄 */
ACIDefine *m_def = NULL; /* 定义句柄 */
typedef struct
{
int sID;
int sCol1;
} Record;
int main()
{
/*----------变量定义-------------*/
sword r = ACI_SUCCESS;
char *m_dblink = "127.0.0.1:2003/OSRDB";
char *m_dbuser = "SYSDBA";
char *m_dbpwd = "szoscar55";
char ssql[] = "select * from mt_t where id=:id";
int id = 10;
Record rec = { 1,2 };
/*----------分配并初始化各类应用句柄-------------*/
r = ACIInitialize(ACI_DEFAULT, NULL, NULL, NULL, NULL);
r = ACIEnvInit(&m_penv, ACI_DEFAULT, 0, 0);
r = ACIHandleAlloc(m_penv, (void**)&m_perr, ACI_HTYPE_ERROR, 0, 0);
r = ACIHandleAlloc(m_penv, (void**)&m_pstmt, ACI_HTYPE_STMT, 0, 0);
/*----------连接数据库-------------*/
r = ACILogon(m_penv, m_perr, &m_psvc, (const OraText *)m_dbuser, strlen(m_dbuser), (const OraText *)m_dbpwd, strlen(m_dbpwd), (const OraText *)m_dblink, strlen(m_dblink));
/*----------准备 SQL 语句-------------*/
r = ACIStmtPrepare(m_pstmt, m_perr, (OraText*)ssql, strlen(ssql), ACI_HTYPE_ERROR, ACI_DEFAULT);
/*----------按位置进行绑定-------------*/
r = ACIBindByPos(m_pstmt, &m_bnd, m_perr, 1, (void *)&id, sizeof(id), SQLT_INT, (void*)0, (ub2*)0, (ub2*)0, 0, 0, ACI_DEFAULT);
/*----------按位置进行定义-------------*/
r = ACIDefineByPos(m_pstmt, &m_def, m_perr, 1, (void*)&rec.sID, sizeof(rec.sID), SQLT_INT, (void*)0, 0, 0, ACI_DEFAULT);
r = ACIDefineByPos(m_pstmt, &m_def, m_perr, 2, (void *)&rec.sCol1, sizeof(rec.sCol1), SQLT_INT, (void*)0, 0, 0, ACI_DEFAULT);
/*----------执行 SQL 语句-------------*/
r = ACIStmtExecute(m_psvc, m_pstmt, m_perr, 0, 0, 0, 0, ACI_DEFAULT);
/*----------结果获取-------------*/
while (((r = ACIStmtFetch(m_pstmt, m_perr, 0, ACI_FETCH_NEXT, ACI_DEFAULT)) != ACI_NO_DATA))
{
printf("%d, %d \n", rec.sID, rec.sCol1);
}
}
Text类型读取
#include <iostream>
#include <oscar/aci.h>
#include <string.h>
ACIEnv *m_penv = NULL;
ACIError *m_perr = NULL;
ACIServer *m_psrv = NULL;
ACISvcCtx *m_psvc = NULL;
ACISession *m_pses = NULL;
ACIStmt *m_pstmt = NULL;
ACIBind *m_pbnd = NULL;
ACIDefine *m_pdef = NULL;
int main()
{
sword r = ACI_SUCCESS;
ub1 errbuf[64] = { 0 }; //获取错误信息的缓冲区
ub1 sqlstate[64] = { 0 }; //ACIErroGet() 的第三个参数变量
sb4 ercodep = 0;
ub2 *rlp = NULL, rcodep = NULL;
char dsql[] = "drop table tt";
char createSql[] = "create table tt(Profession text)";//创建表
char insql[] = "insert into tt values(:1)";//插入数据
char ssql[] = "select * from tt";//查询数据
char *m_dblink = (char *)"127.0.0.1:2003/OSRDB";
char *m_dbuser = (char *) "SYSDBA";
char *m_dbpwd = (char *)"szoscar55";
//初始化环境句柄
r = ACIInitialize(ACI_DEFAULT, NULL, NULL, NULL, NULL);
r = ACIEnvInit(&m_penv, ACI_DEFAULT, 0, 0);
//分配并初始化各类句柄
ACIHandleAlloc(m_penv, (void**)&m_perr, ACI_HTYPE_ERROR, 0, 0);
ACIHandleAlloc(m_penv, (void**)&m_psrv, ACI_HTYPE_SERVER, 0, 0);
ACIHandleAlloc(m_penv, (void**)&m_psvc, ACI_HTYPE_SVCCTX, 0, 0);
ACIHandleAlloc(m_penv, (void**)&m_pses, ACI_HTYPE_SESSION, 0, 0);
ACIHandleAlloc(m_penv, (void**)&m_pstmt, ACI_HTYPE_STMT, 0, 0);
//连接数据库
r = ACILogon(m_penv, m_perr, &m_psvc, (const OraText*)m_dbuser, strlen(m_dbuser),
(const OraText*)m_dbpwd, strlen(m_dbpwd), (const OraText*)m_dblink, strlen(m_dblink));
r = ACIStmtPrepare(m_pstmt, m_perr, (OraText*)dsql, strlen(dsql), ACI_HTYPE_ERROR, ACI_DEFAULT);
r = ACIStmtExecute(m_psvc, m_pstmt, m_perr, 1, 0, 0, 0, ACI_DEFAULT);
//创建数据库
r = ACIStmtPrepare(m_pstmt, m_perr, (OraText*)createSql, strlen(createSql), ACI_HTYPE_ERROR, ACI_DEFAULT);
r = ACIStmtExecute(m_psvc, m_pstmt, m_perr, 1, 0, 0, 0, ACI_DEFAULT);
//插入数据
r = ACIStmtPrepare(m_pstmt, m_perr, (OraText*)insql, strlen(insql), ACI_HTYPE_ERROR, ACI_DEFAULT);
char profession[5][16] = { "小品演员","歌手","相声演员","演员、歌手","演员、歌手" };
int indp3[] = { 0,0,0,0,0 };
ub2 alenp3[] = { 16,16,16,16,16 };
r = ACIBindByPos(m_pstmt, &m_pbnd, m_perr, 1, (void*)profession[0], sizeof(profession[0]), SQLT_STR, indp3, alenp3, 0, 5, 0, ACI_DEFAULT);
r = ACIBindArrayOfStruct(m_pbnd, m_perr, sizeof(profession[0]), sizeof(int), sizeof(ub2), 0);
r = ACIStmtExecute(m_psvc, m_pstmt, m_perr, 5/* 总共有 6 行 */, 0, 0, 0, ACI_DEFAULT);
ACITransCommit(m_psvc, m_perr, ACI_DEFAULT);
//查询
char profession3[6][16] = { 0 };
r = ACIStmtPrepare(m_pstmt, m_perr, (OraText*)ssql, strlen(ssql), ACI_HTYPE_ERROR, ACI_DEFAULT);
r = ACIDefineByPos(m_pstmt, &m_pdef, m_perr, 1, (void*)profession3[0], sizeof(profession3[0]), SQLT_STR,
(void*)0, (ub2*)rlp, (ub2*)rcodep, ACI_DEFAULT);
r = ACIDefineArrayOfStruct(m_pdef, m_perr, sizeof(profession3[0]), 0, 0, 0);
r = ACIStmtExecute(m_psvc, m_pstmt, m_perr, 0, 0, 0, 0, ACI_DEFAULT);
while ((r = ACIStmtFetch(m_pstmt, m_perr, 5, ACI_FETCH_NEXT, ACI_DEFAULT)) != ACI_NO_DATA)
{
int i;
for (i = 0; i < 5; i++)
printf("%s\n", profession3[i]);
}
return 0;
}
函数使用
ACIStmtFetch()
作用:从查询中获取行。
sword ACIStmtFetch ( ACIStmt *stmtp,ACIError *errhp,ub4 nrows,ub2 orientation,ub4 mode );
• stmthp (in)
指向返回的语句句柄的指针。
• errhp (IN)
指向用于诊断的错误句柄的指针。
• nrows (IN)
从当前位置获取的行数,如果在 nrows 参数设置为 0 的情况下调用ACIStmtFetch ,则将关闭游标
• orientation (IN)
唯一可接受的值为 ACI_FETCH_NEXT,这也是默认值。
• mode (IN)
支持 ACI_DEFAULT.
方向设置为 ACI_FETCH_RELATIVE 的 fetchOffset 等效于所有以下各项:
ACI_FETCH_CURRENT 的 fetchOffset 值等于 0
ACI_FETCH_NEXT 的值 fetchOffset 等于 1
ACI_FETCH_PRIOR 的值 fetchOffset 等于-1
ACIStmtPrepare()
作用:
准备要执行的 SQL 或 PL / SQL 语句。不推荐使用此功能。
sword ACIStmtPrepare ( ACIStmt *stmtp,ACIError *errhp,const OraText *stmt,ub4 tmt_len,ub4 language,ub4 mode );
• stmtp (IN)
与要执行的语句关联的语句句柄。默认情况下,它在派生其的环境句柄中包含编码设置。只能在 UTF-16 环
境中以 UTF-16 编码准备语句。
• errhp (IN)
当发生错误时,可以将错误句柄传递给ACIErrorGet 以获取诊断信息。
• stmt (IN)
要执行的 SQL 或 PL / SQL 语句。必须是以 NULL 结尾的字符串。也就是说,根据编码,结束字符为 NULL
字节数。该语句必须使用先前对ACIEnvNlsCreate 的调用的 charset 参数指定的编码。
始终将参数强制转换为(text * )。在 UTF-16 中准备好语句后,绑定和定义缓冲区的字符集默认为 UTF-16。
• stmt_len (IN)
语句的长度(以字符或字节数为单位),取决于编码。不能为零。
• language (IN)
aci库的位置在/opt/Shentong/drivers/aci目录下