c - 错误: Define not done before fetch or execute and fetch

标签 c database oracle oracle-call-interface

我的应用程序从外部源(配置文件)接收查询,因此它必须从查询结果中获取列。我有一些代码:

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:在获取或执行和获取之前未完成定义。我的应用程序说列数与查询匹配并且绑定(bind)正常。我不知道该怎么办。

最佳答案

您需要移动此行:

status = OCIStmtPrepare(statementHandler, errhp, statement, (ub4) strlen((char *) statement), (ub4)OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);

... 在您开始调用 OCIDefineByPos(statementHandler, ...) 之前.

这可能是 executeStatement 中的第一个 OCI 调用真的,在你对 structureHandler 做任何事情之前。但它需要在 for (int a = 0; a < numcols; ++a) 之前无论如何,循环。

我相信在早期版本(9i 和之前的版本?)中,该顺序并没有严格执行,但现在您必须在定义绑定(bind)变量之前做好准备。

关于c - 错误: Define not done before fetch or execute and fetch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30484087/

相关文章:

C变量已经有值了吗?

c - 如何调用缓冲区溢出?

mysql - 保存多语言数据的最佳数据库结构是什么?

java - 使用jdbc在oracle中将InputStream保存为clob

oracle - 在 Oracle 中检查行是否存在的最快查询?

java - 使用 JPA 和 Hibernate 将 Java boolean 值映射到 Oracle Number 列

java - 在 LuaJ 中需要 Java 类

c - 将字符串插入双数组

database - "Parametrized"数据库模型&后端存储系统以及数据挖掘操​​作

.net - 如何处理数据库事务中的文件删除?