【问题标题】:Passing an argument to an Oracle Stored Procedure将参数传递给 Oracle 存储过程
【发布时间】:2012-08-17 20:53:28
【问题描述】:

这可能是以前问过的,所以如果重复,我很抱歉。如果您可以链接到我可以找到答案的地方,我将不胜感激。我已经查看了其他答案和谷歌,但似乎还没有任何效果。 所以...

我在 Oracle 11g 中有一个存储过程(我无法更改),我必须使用 OCI(这里没有选择)。

存储过程声明如下:

PROCEDURE GetEmployee(EID IN NUMBER, rcursor IN OUT cursor_type);

如何在 C 中调用它?

我尝试使用the OCI example here作为基础,修改如下:

char * query =  "DECLARE \
     EID NUMBER; \
     RCURSOR CORP.EMPASSIST.cursor_type; \
     BEGIN \
       EID:= NULL; \
       RCURSOR := NULL; \
       EMPASSIST.GetEmployee( EID=> EID, RCURSOR => RCURSOR ); \
       :RCURSOR := RCURSOR; --<-- Cursor \
     END;";

OCIError * db_error;
OCIStmt * statement;
OCIEnv * environment;
OCIServer * server;
OCISession * session;
OCISvcCtx * service;

OCIBind * cursor_bind;
OCIBind * eid_bind;
OCIStmt * cursor_stm;
OCIStmt * eid_stm;

retval += OCIStmtPrepare(statement, db_error, (OraText *) query, strlen(query), OCI_NTV_SYNTAX, OCI_DEFAULT);
retval += OCIHandleAlloc(environment, (void **) &eid_stm, OCI_HTYPE_STMT, 0, NULL);
retval += OCIHandleAlloc(environment, (void **) &cursor_stm, OCI_HTYPE_STMT, 0, NULL);
retval += OCIBindByPos(statement, &eid_bind, db_error, 1, &eid_stm, 0, SQLT_NUM, NULL, 0, NULL, 0, 0, OCI_DEFAULT);
retval += OCIBindByPos(statement, &cursor_bind, db_error, 2, &cursor_stm, 0, SQLT_RSET, NULL, 0, NULL, 0, 0, OCI_DEFAULT);

retval += OCIStmtExecute(service, statement, db_error, 1, 0, NULL, NULL, OCI_COMMIT_ON_SUCCESS);

但这似乎对我不起作用。所有句柄分配似乎都工作得很好。没有错误。

但是,它在 OCIStmtExecute 步骤上失败。之后我必须 BindByPos,它们也失败了,但我猜那是因为语句执行失败。

请帮忙!

============================================== ===============================

已修复:发布答案以防对其他人有所帮助

【问题讨论】:

  • 你看到了什么确切的失败?另外我认为,由于您要连接到 Oracle,Pro*C(预编译器)将是一个更好的选择。在Pro*C 中执行此操作会容易 n 倍。 HerePro*C 的一些方向。
  • 语句执行良好。结果就是垃圾。当我打印出定义变量时,我得到了奇怪的值。但是,当我在 sqlplus 中运行相同的东西时,我得到了很好的结果。

标签: c oracle stored-procedures oracle-call-interface


【解决方案1】:

如果您发布实际错误会有所帮助。

但是,与命名数据类型一样,绑定 REF 是一个两步过程。首先调用 OCIBindByName() 或 OCIBindByPos(),然后调用 OCIBindObject()。

REF 使用 SQLT_REF 数据类型绑定。当使用 SQLT_REF 时,被绑定的程序变量必须是 OCIRef * 类型。

通过继承和 REF 可替换性,您可以将 REF 值绑定到子类型实例,在该实例中,需要 REF 到超类型。

【讨论】:

  • 语句执行良好。结果就是垃圾。当我打印出定义变量时,我得到了奇怪的值。但是,当我在 sqlplus 中运行相同的东西时,我得到了很好的结果。
【解决方案2】:

改变:

char * query =  "DECLARE \ 
 EID NUMBER; \ 
 RCURSOR CORP.EMPASSIST.cursor_type; \ 
 BEGIN \ 
   EID:= NULL; \ 
   RCURSOR := NULL; \ 
   EMPASSIST.GetEmployee( EID=> EID, RCURSOR => RCURSOR ); \ 
   :RCURSOR := RCURSOR; --<-- Cursor \ 
 END;"; 

int eid = /* whatever value */;
char * query_template = "CALL EMPASSIST.GetEmployee(%d, :RCURSOR)";
char query[1023] =  {'\0'};
snprintf(query, sizeof(query) - 1, query_template, eid);

把剩下的改成:

OCIError * db_error;   
OCIStmt * statement;   
OCIEnv * environment;   
OCISvcCtx * service;   

OCIBind * cursor_bind;   
OCIStmt * cursor_stm;   

retval += OCIHandleAlloc(environment, (void **) &statement, OCI_HTYPE_STMT, 0, NULL);
retval += OCIStmtPrepare(statement, db_error, (OraText *) query, strlen(query), OCI_NTV_SYNTAX, OCI_DEFAULT);   
retval += OCIHandleAlloc(environment, (void **) &cursor_stm, OCI_HTYPE_STMT, 0, NULL);   
retval += OCIBindByName(statement, &cursorbind, db_error, (OraText *) ":RCURSOR", strlen(":RCURSOR"), &cursor, 0, SQLT_RSET, 0, 0, 0, 0, 0, OCI_DEFAULT);   

retval += OCIStmtExecute(service, statement, db_error, 1, 0, NULL, NULL, OCI_COMMIT_ON_SUCCESS);   

【讨论】:

    猜你喜欢
    • 2016-04-05
    • 2016-02-02
    • 2019-06-03
    • 2013-10-24
    • 2020-03-05
    • 2023-03-22
    相关资源
    最近更新 更多