OCI介面學習筆記--基本理解(二)

人稱小強發表於2012-12-24

一. Oracle oci工具包安裝:
$ORACLE_HOME\BIN:執行檔案和help檔案
$ORACLE_HOME\OCI\INCLUDE:標頭檔案
$ORACLE_HOME\OCI\LIB\BC:  for Borlanf C++的OCI庫
$ORACLE_HOME\OCI\LIB\MSVC:  for MS Visual C++的CI庫
如果是unix下,對於ORACLE8i,則OCI庫在$ORACLE_HOME/
lib下,如果是9i,則在$ORACLE_HOME/lib32下,庫檔名一般為libclntsh.so

二、一個資料庫OCI操作一般流程

  • 初始化OCI環境
  • 申請控制程式碼
  • 連線資料庫
  • 建立會話
  • 執行SQL操作(在這個過程中包括:(1)準備SQL語句。(2)在SQL語句中繫結需要輸入到SQL語句中的變數。(3)執行SQL語句。(4)獲取SQL中的輸出描述。(5)定義輸出變數。(6)獲取資料)
  • 斷開會話
  • 斷開伺服器
  • 釋放資源

三、例項分析

先通過一段較為簡單的程式碼大致理解一下OCI程式設計:

  1. #include <oci.h>
  2. #include <iostream>
  3. #include <string>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. using namespace std;

  7. //存放查詢資料的結構體
  8. struct result
  9. {
  10.     char ename[20];
  11.     char cname[20];
  12.     result()
  13.     {
  14.         memset(ename, '\0', sizeof(ename));
  15.         memset(cname, '\0', sizeof(cname));
  16.     }
  17. };

  18. int main()
  19. {
  20.     // 初始化 OCI 環境控制程式碼指標
  21.     OCIEnv *envhpp = NULL;
  22.     // 初始化伺服器控制程式碼
  23.     OCIServer *servhpp = NULL;
  24.     // 用於捕獲 OCI 錯誤資訊
  25.     OCIError *errhpp = NULL;
  26.     // 初始化會話控制程式碼
  27.     OCISession *usrhpp = NULL;
  28.     // 初始化服務上下文控制程式碼
  29.     OCISvcCtx *svchpp = NULL;
  30.     // 初始化表示式控制程式碼
  31.     OCIStmt *stmthpp = NULL;

  32.     string server="mydb";

  33.     // 建立 OCI 環境 , 並設定環境控制程式碼。
  34.     sword swResult = OCIEnvCreate(&envhpp, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL);
  35.     if (swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
  36.     {
  37.         cout << "Oracle environment initialization error!" << endl;
  38.         exit(1);
  39.     }
  40.     cout << "Oracle environment initialization success!" << endl;

  41.     // 建立錯誤控制程式碼
  42.     OCIHandleAlloc((dvoid *)envhpp, (dvoid **)&errhpp, OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0);

  43.     // 建立服務控制程式碼
  44.     OCIHandleAlloc((dvoid *)envhpp, (dvoid **)&servhpp, OCI_HTYPE_SERVER, (size_t)0, (dvoid **)0);

  45.     // 連線伺服器,如果失敗則獲取錯誤碼
  46.     if (OCIServerAttach(servhpp, errhpp, (text *)server.c_str(), strlen(server.c_str()), 0) != OCI_SUCCESS)
  47.     {
  48.         int errcno;
  49.         char errbuf[512] = "";
  50.         sb4 errcode;

  51.         // 獲取錯誤指標和 OCI 錯誤程式碼
  52.         OCIErrorGet((dvoid *)errhpp, (ub4)1, (text *)NULL, &errcode, (ub1 *)errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
  53.         errcno = errcode;

  54.         cout << "Oracle server attach error:" << errbuf << endl;
  55.         OCIHandleFree((dvoid *)envhpp,OCI_HTYPE_ENV);
  56.         OCIHandleFree((dvoid *)servhpp,OCI_HTYPE_SERVER);
  57.         OCIHandleFree((dvoid *)errhpp,OCI_HTYPE_ERROR);
  58.         exit(1);
  59.     }
  60.     cout << "Oracle server attach success!"<< endl;

  61.     /***************** 連線資料庫 ****************/
  62.     string user = "user";
  63.     string pas = "passwd";
  64.     errhpp = NULL;

  65.     // 建立錯誤控制程式碼
  66.     (void) OCIHandleAlloc((dvoid *)envhpp, (dvoid **)&errhpp, OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0);
  67.     // 建立服務上下文控制程式碼
  68.     (void) OCIHandleAlloc((dvoid *)envhpp, (dvoid **)&svchpp, OCI_HTYPE_SVCCTX, (size_t) 0, (dvoid **)0);
  69.     // 設定屬性
  70.     (void) OCIAttrSet((dvoid *)svchpp, OCI_HTYPE_SVCCTX, (dvoid *)servhpp, (ub4)0, OCI_ATTR_SERVER, (OCIError *)errhpp);
  71.     // 建立使用者連線控制程式碼
  72.     (void) OCIHandleAlloc((dvoid *)envhpp, (dvoid **)&usrhpp, (ub4)OCI_HTYPE_SESSION, (size_t) 0, (dvoid **)0);
  73.     // 設定使用者名稱、密碼
  74.     (void) OCIAttrSet((dvoid *)usrhpp, (ub4)OCI_HTYPE_SESSION, (dvoid *)user.c_str(), (ub4)strlen(user.c_str()), (ub4)OCI_ATTR_USERNAME, errhpp);
  75.     (void) OCIAttrSet((dvoid *)usrhpp, (ub4)OCI_HTYPE_SESSION, (dvoid *)pas.c_str(), (ub4)strlen(pas.c_str()), (ub4)OCI_ATTR_PASSWORD, errhpp);

  76.     // 建立會話連線
  77.     if(OCISessionBegin(svchpp, errhpp, usrhpp, OCI_CRED_RDBMS, (ub4)OCI_DEFAULT) != OCI_SUCCESS)
  78.     {
  79.         int errcno;
  80.         char errbuf[512]={'\0'};
  81.         sb4 errcode;
  82.        
  83.         // 獲取錯誤指標和 OCI 錯誤程式碼
  84.         OCIErrorGet((dvoid *)errhpp, (ub4)1, (text *)NULL, &errcode, (ub1 *)errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
  85.         errcno = errcode;
  86.         cout << "User session error:" << errbuf << endl;
  87.         OCIHandleFree((dvoid *)errhpp,OCI_HTYPE_ERROR);
  88.         OCIHandleFree((dvoid *)usrhpp,OCI_HTYPE_SESSION);
  89.         OCIHandleFree((dvoid *)svchpp,OCI_HTYPE_SVCCTX);
  90.         exit(1);
  91.     }
  92.     cout << "user session success!" << endl;
  93.    
  94.     (void) OCIAttrSet((dvoid *)svchpp, (ub4) OCI_HTYPE_SVCCTX, (dvoid *)usrhpp, (ub4)0, (ub4)OCI_ATTR_SESSION, errhpp);

  95.     /*************** 執行 查詢SQL 語句 ******************/
  96.     errhpp = NULL;

  97.     // 建立一個表示式控制程式碼
  98.     if (OCIHandleAlloc((dvoid *)envhpp, (dvoid **)&stmthpp, OCI_HTYPE_STMT, (size_t)0, (dvoid **)0) != OCI_SUCCESS)
  99.     {
  100.         cout << "Create STMT error !" << endl;
  101.         exit(1);
  102.     }
  103.     cout << "Create stmt success !" << endl;
  104.    
  105.     // 建立錯誤控制程式碼
  106.     OCIHandleAlloc((dvoid *)envhpp, (dvoid **)&errhpp, OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0);
  107.    
  108.     // Select語句
  109.     char sql[255] = "select col1, col2 from table1 ";
  110.    
  111.     if (OCIStmtPrepare(stmthpp, errhpp, (text *)sql, (ub4)strlen(sql), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) != OCI_SUCCESS)
  112.     {
  113.          cout << "Create prepare error!" << sql << endl;
  114.          exit(1);
  115.     }
  116.     cout << "Create prepare success!" << endl;

  117.     /********* 繫結引數 ***********/
  118.     // 申請繫結欄位的控制程式碼
  119.     OCIDefine *bhp1 = NULL;
  120.     OCIDefine *bhp2 = NULL;
  121.    
  122.     // 存放資料的結構
  123.     struct result rst;
  124.    
  125.     // 指定提取資料長度
  126.     ub2 datalen = 0;
  127.     // 定義指示器變數 , 用於取可能存在空值的欄位
  128.     char isnul[6] = "";
  129.     // 定義輸出變數 ,
  130.     OCIDefineByPos(stmthpp, &bhp1, errhpp, 1, (dvoid *)&rst.ename, sizeof(rst.ename), SQLT_CHR, NULL, &datalen, NULL, OCI_DEFAULT);
  131.     OCIDefineByPos(stmthpp, &bhp2, errhpp, 2, (dvoid *)&rst.cname, sizeof(rst.cname), SQLT_STR, NULL, &datalen, NULL, OCI_DEFAULT);

  132.     // 獲取 SQL 語句型別
  133.     ub2 stmt_type;
  134.     OCIAttrGet ((dvoid *)stmthpp, (ub4)OCI_HTYPE_STMT, (dvoid *)&stmt_type, (ub4 *)0, (ub4)OCI_ATTR_STMT_TYPE, errhpp);
  135.    
  136.     // 執行 SQL 語句
  137.     OCIStmtExecute(svchpp, stmthpp, errhpp, (ub4)0, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, OCI_DEFAULT);

  138.     // 獲取查詢資訊
  139.     int rows_fetched;
  140.     do
  141.     {
  142.         cerr << rst.ename<< " ";
  143.         cerr << rst.cname<< " \n";
  144.     }
  145.     while(OCIStmtFetch2(stmthpp, errhpp, 1, OCI_FETCH_NEXT, 1, OCI_DEFAULT) != OCI_NO_DATA);

  146.     // 獲得記錄條數
  147.     OCIAttrGet((CONST void *)stmthpp, OCI_HTYPE_STMT, (void *)&rows_fetched, (ub4 *)sizeof(rows_fetched), OCI_ATTR_ROW_COUNT, errhpp);
  148.     cout << " rows :" << rows_fetched << endl;

  149.     /*************** 執行 新增SQL 語句 ******************/
  150.     if (OCIHandleAlloc((dvoid *)envhpp, (dvoid **)&stmthpp, OCI_HTYPE_STMT, (size_t)0, (dvoid **)0) != OCI_SUCCESS)
  151.     {
  152.         cout << "Create STMT error !" << endl;
  153.         exit(1);
  154.     }
  155.     cout << "Create stmt success !" << endl;

  156.     OCIHandleAlloc((dvoid *)envhpp, (dvoid **)&errhpp, OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0);

  157.     // Insert語句
  158.     char sql2[255] = "insert into table1 (col1, col2) values('testoci', 'testoci')";
  159.    
  160.     // 準備Sql語句
  161.     if (OCIStmtPrepare(stmthpp, errhpp, (text *)sql2, (ub4)strlen(sql2), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) != OCI_SUCCESS)
  162.     {
  163.          cout << "Create prepare error!" << sql2 << endl;
  164.          exit(1);
  165.     }
  166.     cout << "Create prepare success!" << endl;
  167.    
  168.     // 執行SQL 語句
  169.     OCIStmtExecute(svchpp, stmthpp, errhpp, (ub4)1, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, OCI_DEFAULT);

  170.     // 斷開使用者會話
  171.     OCILogoff(svchpp, errhpp);
  172.    
  173.     // 斷開伺服器連線
  174.     OCIServerDetach(servhpp, errhpp, OCI_DEFAULT);
  175.    
  176.     // 釋放資源
  177.     OCIHandleFree((dvoid *) stmthpp, OCI_HTYPE_STMT);
  178.     OCIHandleFree((dvoid *) svchpp, OCI_HTYPE_SVCCTX);
  179.     OCIHandleFree((dvoid *) servhpp, OCI_HTYPE_SERVER);
  180.     OCIHandleFree((dvoid *) errhpp, OCI_HTYPE_ERROR);

  181.     return 0;
  182. }

 

相關文章