OCI(Oracle Call Interface)是Oracle提供的一個強大的C語言API,它能夠讓我們輕松地訪問Oracle數據庫,進行數據的增刪改查等操作。OCI使用起來雖然不如PL/SQL那樣簡單,但是卻能夠提供更為靈活的操作,能夠滿足更多特定場景下的需求。下面,我們來看看OCI如何訪問Oracle數據庫。
首先,我們需要一個OCI環境句柄(OCIEnv*),然后創建一個OCI錯誤句柄(OCIError*),這個錯誤句柄將會用于記錄操作過程中的錯誤信息。接著,我們需要連接到Oracle數據庫,需要使用OCI的連接句柄(OCISvcCtx*)和OCI會話句柄(OCISession*)來實現連接操作。下面是示例代碼:
OCIEnv* envhp; OCIError* errhp; OCISvcCtx* svchp; OCISession* usrhp; text* dbname = (text*) "ORCL"; text* username = (text*) "username"; text* password = (text*) "password"; ub4 dbname_len = strlen((char*) dbname); ub4 username_len = strlen((char*) username); ub4 password_len = strlen((char*) password); if (OCIEnvCreate(&envhp, OCI_THREADED, NULL, NULL, NULL,NULL,0,NULL)) { printf("OCIEnvCreate failed\n"); return -1; } if (OCIHandleAlloc(envhp, (dvoid**)&errhp, OCI_HTYPE_ERROR, 0, NULL)) { printf("OCIHandleAlloc OCI_HTYPE_ERROR failed\n"); return -1; } if (OCIHandleAlloc(envhp, (dvoid**)&svchp, OCI_HTYPE_SVCCTX, 0, NULL)) { printf("OCIHandleAlloc OCI_HTYPE_SVCCTX failed\n"); return -1; } if (OCIHandleAlloc(envhp, (dvoid**)&usrhp, OCI_HTYPE_SESSION, 0, NULL)) { printf("OCIHandleAlloc OCI_HTYPE_SESSION failed\n"); return -1; } if (OCILogon2(envhp, errhp, &svchp, (const OraText*) dbname, dbname_len, (const OraText*) username, username_len, (const OraText*) password, password_len, OCI_DEFAULT)) { printf("OCILogon2 failed\n"); return -1; }
通過上面的代碼,我們就成功地連接到了Oracle數據庫。接下來,我們可以通過OCI的語句句柄(OCIStmt*)來執行SQL語句。例如,我們可以查詢一個名為“t_user”的數據表中的所有數據,如下:
OCIStmt* stmthp; text* sql = (text*) "SELECT * FROM t_user"; ub4 sql_len = strlen((char*) sql); if (OCIHandleAlloc(envhp, (dvoid**)&stmthp, OCI_HTYPE_STMT, 0, NULL)) { printf("OCIHandleAlloc OCI_HTYPE_STMT failed\n"); return -1; } if (OCIStmtPrepare(stmthp, errhp, (const OraText*) sql, sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT)) { printf("OCIStmtPrepare failed\n"); return -1; } if (OCIStmtExecute(svchp, stmthp, errhp, 0, 0, NULL, NULL, OCI_DEFAULT)) { printf("OCIStmtExecute failed\n"); return -1; } OCIParam* colparam; ub1 coltype; sb2 colname[30]; ub2 colname_len; ub2 colnamelen; ub4 i = 1; while (!OCIStmtFetch(stmthp, errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT)) { if (OCIParamGet(stmthp, OCI_HTYPE_STMT, errhp, (dvoid**)&colparam, i)) { printf("OCIParamGet failed\n"); return -1; } if (OCIAttrGet(colparam, OCI_DTYPE_PARAM, &(dvoid*)colname, &(ub4)colnamelen, OCI_ATTR_NAME, errhp)) { printf("OCIAttrGet OCI_ATTR_NAME failed\n"); return -1; } colname_len = colnamelen / sizeof(sb2); colname[colname_len] = 0; if (OCIAttrGet(colparam, OCI_DTYPE_PARAM, &coltype, 0, OCI_ATTR_DATA_TYPE, errhp)) { printf("OCIAttrGet OCI_ATTR_DATA_TYPE failed\n"); return -1; } if (coltype == SQLT_STR) { text strbuf[100]; ub2 strbuf_len; if (OCIAttrGet(colparam, OCI_DTYPE_PARAM, &strbuf, &strbuf_len, OCI_ATTR_DATA_SIZE, errhp)) { printf("OCIAttrGet OCI_ATTR_DATA_SIZE failed\n"); return -1; } if (OCIAttrGet(colparam, OCI_DTYPE_PARAM, &strbuf, &strbuf_len, OCI_ATTR_DATA, errhp)) { printf("OCIAttrGet OCI_ATTR_DATA failed\n"); return -1; } printf("%s\n", strbuf); } i++; }
上面的代碼中,我們先通過OCIStmtPrepare方法準備好了一個SELECT語句,然后通過OCIStmtExecute方法執行這個語句,獲取到了查詢結果集。接著,我們通過OCIParamGet方法獲取到每個字段,通過OCIAttrGet方法獲取字段的名稱和類型,并使用if語句判斷該字段的類型是否為字符串類型。如果是字符串類型,則通過OCIAttrGet方法獲取到該字段的值并輸出。
總之,OCI是一個非常強大的API,它提供了大量的函數和方法,能夠滿足各種不同場景下的需求。在使用OCI時,應該注意靈活運用各種方法,并根據具體情況進行調整和優化。