1

これは以前に尋ねられた可能性があるので、これが繰り返されると申し訳ありません。私が答えを見つけることができる場所にリンクすることができれば、私は本当にそれをいただければ幸いです。私は他の答えやグーグルを見回しましたが、まだ何もうまくいかなかったようです。それで...

Oracle 11gにストアドプロシージャがあり(変更できません)、OCIを使用する必要があります(ここでは選択できません)。

ストアドプロシージャの宣言は次のようになります。

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

これをCで呼び出すにはどうすればよいですか?

ここでOCIの例を基礎として使用し、次のように変更してみました。

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を実行する必要があり、それらも失敗しますが、これはステートメントの実行が失敗したためだと思います。

助けてください!

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

修正:他の誰かを助ける場合に備えて回答を投稿する

4

2 に答える 2

0

実際のエラーを投稿すると役に立ちます。

ただし、名前付きデータ型と同様に、REFのバインドは2段階のプロセスです。まず、OCIBindByName()またはOCIBindByPos()を呼び出してから、OCIBindObject()を呼び出します。

REFは、SQLT_REFデータ型を使用してバインドされます。SQLT_REFを使用する場合、バインドされるプログラム変数はOCIRef*型である必要があります。

継承とREFの代替可能性を使用すると、スーパータイプへのREFが期待されるサブタイプインスタンスにREF値をバインドできます。

于 2012-08-18T20:03:03.950 に答える
0

かわった:

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);   
于 2012-08-21T18:50:18.973 に答える