我的应用程序从外部源(配置文件)接收查询,因此它必须从查询结果中获取列。我有一些代码:
typedef union _DbField {
text text[512];
sword integer;
double precise;
} DbField;
typedef struct _Arg {
size_t argSize;
DbField field;
} Arg;
OCIEnv *envhp;
OCISession *authp = (OCISession *) 0;
OCIError *errhp;
OCISvcCtx *svchp;
OCIServer *srvhp;
OCIStmt *statementHandler;
OCIDefine *defnp = (OCIDefine *) 0;
sword status;
...
//int main()
status = OCIEnvCreate((OCIEnv **) &envhp, (ub4) OCI_DEFAULT, (dvoid *) 0,
(dvoid * (*)(dvoid *, size_t)) 0, (dvoid * (*)(dvoid *, dvoid *, size_t)) 0,
(void (*)(dvoid *, dvoid *)) 0, (size_t) 0, (dvoid **) 0);
checkError(0, __LINE__);
status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &errhp, OCI_HTYPE_ERROR, (size_t) 0,
(dvoid **) 0);
checkError(0, __LINE__);
status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &srvhp, OCI_HTYPE_SERVER, (size_t) 0,
(dvoid **) 0);
checkError(0, __LINE__);
status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &svchp, OCI_HTYPE_SVCCTX, (size_t) 0,
(dvoid **) 0);
checkError(0, __LINE__);
status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &statementHandler, OCI_HTYPE_STMT,
(size_t) 0, (dvoid **) 0);
checkError(0, __LINE__);
status = OCIServerAttach(srvhp, errhp, (text *) connection->dbName, (sb4) strlen((char *) connection->dbName), 0);
status = OCIServerAttach(srvhp, errhp, (text *) "", (sb4) strlen((char *) ""), 0);
checkError(0, __LINE__);
status = OCIAttrSet((dvoid *) svchp, OCI_HTYPE_SVCCTX, (dvoid *) srvhp, (ub4) 0,
OCI_ATTR_SERVER, (OCIError *) errhp);
if (status != 0) {
printf("HANDLER ERROR %d !!!\n\n", status);
exit(2);
}
(void) OCIHandleAlloc((dvoid *) envhp, (dvoid **) &authp, (ub4) OCI_HTYPE_SESSION,
(size_t) 0, (dvoid **) 0);
(void) OCIAttrSet((dvoid *) authp, (ub4) OCI_HTYPE_SESSION, (dvoid *) connection->userName,
(ub4) strlen((char *) connection->userName), (ub4) OCI_ATTR_USERNAME, errhp);
(void) OCIAttrSet((dvoid *) authp, (ub4) OCI_HTYPE_SESSION,
(dvoid *) connection->userPassword,
(ub4) strlen((char *) connection->userPassword), (ub4) OCI_ATTR_PASSWORD, errhp);
status = OCISessionBegin(svchp, errhp, authp, OCI_CRED_RDBMS, (ub4) OCI_DEFAULT);
(void) OCIAttrSet((dvoid *) svchp, (ub4) OCI_HTYPE_SVCCTX, (dvoid *) authp, (ub4) 0,
(ub4) OCI_ATTR_SESSION, errhp);
errhp, OCIHandleAlloc((dvoid *) envhp, (dvoid **) &statementHandler, OCI_HTYPE_STMT,
(size_t) 0, (dvoid **) 0);
executeStatement("SELECT * FROM logs order by log_id");
//end of int main()
static inline sword executeStatement(char *statement) {
int rowsFetched = 0;
int forSecond = 0;
ub4 numcols = 0;
ub2 dtype = 0;
OCIStmt *structureHandler;
OCIParam *colhd = (OCIParam *) 0;
char *statementCopy = malloc(strlen(statement));
memcpy(statementCopy, statement, strlen(statement));
status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &structureHandler, OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0);
checkError(1, __LINE__);
status = OCIStmtPrepare(structureHandler, errhp, statementCopy, (ub4) strlen((char *) statement), (ub4)OCI_NTV_SYNTAX, (ub4) OCI_NO_SHARING);
checkError(1, __LINE__);
status = OCIStmtExecute(svchp, structureHandler, errhp, (ub4) 1, (ub4) 0,(const OCISnapshot *) NULL, (OCISnapshot *) NULL, (ub4) OCI_DESCRIBE_ONLY);
checkError(1, __LINE__);
OCIAttrGet((dvoid *)structureHandler, OCI_HTYPE_STMT, (dvoid *)&numcols, (ub4 *)0, OCI_ATTR_PARAM_COUNT, errhp);
ub2 colTypes[numcols];
Arg columns[numcols];
for (int a = 0; a < numcols; ++a) {
OCIParamGet((dvoid *)structureHandler, OCI_HTYPE_STMT, errhp, (dvoid **)&colhd, a+1);
OCIAttrGet((dvoid *)colhd, OCI_DTYPE_PARAM,(dvoid *)&dtype, (ub4 *)0, OCI_ATTR_DATA_TYPE, errhp);
colTypes[a] = dtype;
printf("Coltype %d\t\t", colTypes[a]);
if (colTypes[a] == SQLT_INT || colTypes[a] == SQLT_NUM) {
columns[a].argSize = sizeof(int);
printf("Param is %d INT, size %d ", a, columns[a].argSize);
status = OCIDefineByPos(statementHandler, &defnp, errhp, a+1, (dvoid *)&(columns[a].field.integer), (sword) columns[a].argSize, colTypes[a], (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT);
if (status == 0) {
printf("Param %d bind OK\n", a+1);
} else {
printf("Binding %d param caused error!!!\n", a+1);
}
fflush(stdout);
} else if (colTypes[a] == SQLT_STR || colTypes[a] == SQLT_CLOB) {
columns[a].argSize = sizeof(char)*1024;
status = OCIDefineByPos(statementHandler, &defnp, errhp, a+1, (dvoid *)&(columns[a].field.text), (sword) columns[a].argSize, colTypes[a], (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT);
printf("Param is %d STR, size %d ", a, columns[a].argSize);
if (status == 0) {
printf("Param %d bind OK\n", a+1);
} else {
printf("Binding %d param caused error!!!\n", a+1);
}
fflush(stdout);
} else if (colTypes[a] == SQLT_TIMESTAMP) {
columns[a].argSize = sizeof(char)*768;
status = OCIDefineByPos(statementHandler, &defnp, errhp, a+1, (dvoid *)&(columns[a].field.text), (sword) columns[a].argSize, colTypes[a], (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT);
printf("Param is %d TIMESTAMP, size %d ", a, columns[a].argSize);
if (status == 0) {
printf("Param %d bind OK\n", a+1);
} else {
printf("Binding %d param caused error!!!\n", a+1);
}
fflush(stdout);
} else {
//Other types are not needed for me right now
perror("Invalid column type\n\n");
printf("Other type for [%d]: %d\n", a, colTypes[a]);
fflush(stdout);
exit(3);
}
}
status = OCIStmtPrepare(statementHandler, errhp, statement, (ub4) strlen((char *) statement), (ub4)OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);
checkError(0, __LINE__);
//ERROR IN LINE ABOVE
status = OCIStmtExecute(svchp, statementHandler, errhp, (ub4) 1, (ub4) 0,(const OCISnapshot *) NULL, (OCISnapshot *) NULL, (ub4) OCI_DEFAULT);
checkError(0, __LINE__);
status = OCIAttrGet(statementHandler, OCI_HTYPE_STMT, (void*)&rowsFetched, NULL, OCI_ATTR_ROWS_FETCHED, errhp);
printf("Total rows: %d, status %d.\n", rowsFetched, status);
if (rowsFetched == 0) {
printf("No data!\n");
return OCI_NO_DATA;
}
do {
printf("ROW ");
for (int a = 0; a < numcols; ++a) {
if (colTypes[a] == SQLT_INT || colTypes[a] == SQLT_NUM) {
printf(" INT %d", columns[a].field.integer);
} else if (colTypes[a] == SQLT_STR || colTypes[a] == SQLT_CLOB) {
printf(" TXT %s", columns[a].field.text);
} else if (colTypes[a] == SQLT_TIMESTAMP) {
printf(" TIMESTAMP %s", columns[a].field.text);
} else {
perror("Invalid column type\n\n");
printf("Other type for [%d]: %d\n", a, colTypes[a]);
fflush(stdout);
exit(3);
}
}
printf("\n");
status = OCIStmtFetch2(statementHandler, errhp, 1, OCI_DEFAULT, (sb4) 1, OCI_DEFAULT);
} while (status != OCI_NO_DATA && status != OCI_ERROR);
return OCI_SUCCESS;
}
标记行中的此代码导致错误ORA-24374:在获取或执行和获取之前未定义。我的应用程序说列数与查询匹配,绑定没问题。我不知道该怎么做。
答案 0 :(得分:1)
你需要移动这一行:
status = OCIStmtPrepare(statementHandler, errhp, statement, (ub4) strlen((char *) statement), (ub4)OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);
...在您开始致电OCIDefineByPos(statementHandler, ...)
之前。
在您使用executeStatement
执行任何操作之前,它可能是structureHandler
中的第一个OCI调用。但无论如何,它需要在for (int a = 0; a < numcols; ++a)
循环之前。
我认为在早期版本(9i及之前的版本?)中强行执行的命令并不强烈,但现在您必须先准备好才能定义绑定变量。