轉自:http://kulong0105.blog.163.com/blog/static/174406191201162145944574/html
最近公司作的一個項目,要處理海量數據,數據是存放在Oracle數據庫裏,剛開始用的是ADO訪問,速度極慢,後來改用Proc,效果仍是不如人意,最後才用的OCI。由於以前對OCI不瞭解過,經2個星期的努力,終於完成了對Oracle數據庫中的海量數據的讀取與插入,速度的確很快,測試讀取七千五百萬條數據連一分鐘都不到。linux
以前用Proc,沒用OCI,是由於Proc容易學,OCI相對難學些,提及難學,主要就是由於Oracle提供的一百多個API函數中每一個函數都至少帶有七八個參數,而每一個參數都具備不一樣的重要的意義,一不當心設置錯了,可能會致使潛在的錯誤,調試的時候也很難發現,這個我深有體會啊!sql
下面結合個人學習過程,講一下OCI編程:數據庫
1:環境的配置編程
一:系統環境:要想使用OCI編程須要安裝Oracle的客戶端,而這個普通的客戶端比較大,在Oracle10g版本後推出了大小隻有30M的Instantclient(即時客戶端)做爲Oracle的訪問客戶端。windows
具體的配置能夠參考這裏:http://www.cnblogs.com/ychellboy/archive/2010/04/16/1713884.html數組
二:執行環境:服務器
windows下的配置能夠參考這裏:http://blog.csdn.net/sherlockhua/article/details/4353531oracle
linux下的配置能夠參考這裏:http://blog.csdn.net/sherlockhua/article/details/4353531 app
2:基本理論
㈠首先要建立OCI 環境即建立和初始化OCI 工做環境,其餘的OCI 函數須要OCI 環境才能執行。
㈡分配OCI 環境句柄:它定義全部OCI 函數的調用環境,是其餘句柄的父句柄。( 由OCIEnvInit 或OCIEnvCreate 生成 ) 。
㈢錯誤句柄:做爲一些OCI 函數的參數,用來記錄這些OCI 函數操做過程當中所產生的錯誤,當有錯誤發生時,可用OCIErrorGet() 來讀取錯誤句柄中記錄的錯誤信息。
㈣服務器環境句柄:定義OCI 調用的服務器操做環境,它包含服務器、用戶會話和事務三種句柄。
㈤服務器句柄:標識數據源,它轉換爲與服務器的物理鏈接。
㈥用戶會話句柄:定義用戶角色和權限及OCI 調用的執行環境。
㈦事務句柄:定義執行 SQL 操做的事務環境,事務環境中包含用戶的會話狀態信息。
㈧語句句柄:是一個標識 SQL 語句或 PL/SQL 塊,以及其相關屬性的環境。
㈨Bind/Define句柄:屬於語句句柄的子句柄,由OCI庫隱式自動生成。用戶不須要本身再申請,OCI輸入變量存儲在bind 句柄中,輸出變量存儲在定義句柄中。
注意:Bind/Define 句柄在執行具體的 SQL 語句的時候,被隱含建立並鏈接到表達句柄( Statement Handle )上,當表達句柄釋放時,它們也被隱含釋放。因此在執行每個 sql 語句時,先分配表達句柄,執行結束後,釋放表達句柄,這樣作保證不發生因爲定位句柄和綁定變量句柄引發的內存泄漏。
3:鏈接Oracle數據庫的步驟
OCI 鏈接過程比較複雜,除了分配設置各個基本句柄外,還要明確彼此之間的聯繫,大體流程以下:
建立環境句柄: OCIEnvCreate(&envhp, …);
建立一個指定環境的錯誤句柄: OCIHandleAlloc((dvoid *)envhp, (dvoid **)&errhp,…);
建立一個指定環境的服務器句柄: OCIHandleAlloc((dvoid *)envhp, (dvoid **)&servhp,…);
創建到數據源的訪問路徑 : OCIServerAttach(servhpp, errhpp,…);
建立一個指定環境的服務上下文句柄: (void) OCIHandleAlloc((dvoid *)envhpp,…);
爲指定的句柄及描述符設置特定的屬性: (void) OCIAttrSet((dvoid *)svchpp,…);
建立一個指定環境的用戶鏈接句柄: (void) OCIHandleAlloc((dvoid *)envhpp,…);
爲用戶鏈接句柄設置登陸名及密碼: (void) OCIAttrSet((dvoid *)usrhpp,…);
認證用戶創建一個會話鏈接: OCISessionBegin(svchpp, errhpp,…);
建立一個句子句柄: OCIHandleAlloc((dvoid *)envhpp,…);s
準備 SQL 語句: OCIStmtPrepare(stmthpp, errhpp,…);
綁定輸入變量: OCIBindByPos(stmtp &hBind, errhp,…);
綁定輸出變量: OCIDefineByPos(stmthpp, &bhp1, errhpp,…);
得到 SQL 語句類型: OCIAttrGet ((dvoid *)stmthpp, (ub4)OCI_HTYPE_STMT,…);
執行 SQL 語句: OCIStmtExecute(svchpp, stmthpp,…);
釋放一個會話: OCISessionEnd();
刪除到數據源的訪問 : OCIServerDetach(servhpp, errhpp, OCI_DEFAULT);
釋放句柄: OCIHandleFree((dvoid *) stmthpp, OCI_HTYPE_STMT);
4:經常使用句柄屬性
服務器環境句柄屬性: (OCI_HTYPE_SVCCTX)
OCI_ATTR_SERVER— 設置 / 讀取服務環境的服務器環境屬性
OCI_ATTR_SESSION— 設置 / 讀取服務環境的會話認證環境屬性
OCI_ATTR_TRANS— 設置 / 讀取服務環境的事務環境屬性
用戶會話句柄屬性: (OCI_HTYPE_SESSION)
OCI_ATTR_USERNAME— 設置會話認證所使用的用戶名
OCI_ATTR_PASSWORD— 設置會話認證所使用的用戶口令
服務器句柄: (OCI_HTYPE_SEVER)
OCI_ATTR_NOBLOCKING_MODE— 設置 / 讀取服務器鏈接: =TRUE 時服務器鏈接設置爲非阻塞方式
語句句柄: (OCI_HTYPE_STMT)
OCI_ATTR_ROWS_RETCHED 取得獲取數據記錄數
OCI_ATTR_ROW_COUNT— 只讀,爲當前已處理的行數,其 default=1
OCI_ATTR_STMT_TYPE— 讀取當前 SQL 語句的類型:
Eg : OCI_STMT_BEGIN
OCI_STMT_SELECT OCI_STMT_INSERT
OCI_STMT_UPDATE OCI_STMT_DELETE
OCI_ATTR_PARAM_COUNT—返回語句選擇列表中的列數
5:介紹一下OCI的經常使用函數,這些經常使用函數基本能夠幫助你完成大多數的操做
一:建立OCI環境
sword OCIEnvCreate(
OCIEnv **envhpp, //OCI環境句柄指針
ub4 mode, //初始化模式:OCI_DEFAULT | OCI_THREADED | OCI_OBJECT等
CONST dvoid *ctxp,
CONST dvoid *(*malicfp)(dvoid *ctxp,size_t size),
CONST dvoid *(ralocfp)(dvoid *ctxp,dvoid *memptr,size_t newsize),
CONST void *(*mfreefp)(dvoid *ctxp,dvoid *memptr),
Size_t xstramemsz,
Dvoid **usrmempp
)
eg:建立OCI環境
int nresult=OCIEnvCreate(&envhpp, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL);
二:申請/釋放句柄
sword OCIHandleAlloc(
CONST dvoid *parenth, //新申請句柄的父句柄,通常爲OCI環境句柄
Dvoid **hndlpp, //申請的新句柄
Ub4 type, type, //句柄類型
Size_t xtramem_sz, //申請的內存數
Dvoid **usrmempp //申請到的內存塊指針
)
注: 通常須要申請的句柄有:
服務器句柄OCIServer, 句柄類型OCI_HTYPE_SERVER
錯誤句柄OCIError,用於捕獲OCI錯誤信息, 句柄類型OCI_HTYPE_ERROR
上下文句柄OCISvcCtx, 句柄類型OCI_HTYPE_SVCCTX
事務句柄OCISession, 句柄類型OCI_HTYPE_SESSION
SQL語句句柄OCIStmt, 句柄類型OCI_HTYPE_STMT
eg: 申請一個錯誤句柄OCIError
swResult = OCIHandleAlloc(envhpp, (dvoid *)& errhp, OCI_HTYPE_ERROR, 0, NULL);
if(swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
{ return FALSE; }
釋放句柄
sword OCIHandleFree(
dvoid *hndlp, //要釋放的句柄
ub4 type //句柄類型
)
eg: 釋放語句句柄
OCIHandleFree(stmtp, OCI_HTYPE_STMT)
三:讀取/設置句柄屬性
sword OCIAttrSet(
dvoid *trgthndlp, //需設置的句柄名
ub4 trghndltyp, //句柄類型
dvoid *attributep, //設置的屬性名
ub4 size, //屬性值長度
ub4 attrtype, //屬性類型
OCIError *errhp //錯誤句柄
)
注:通常要設置的屬性有:
服務器實例:
句柄類型OCI_HTYPE_SVCCTX,屬性類型 OCI_ATTR_SERVER
鏈接數據庫的用戶名:
句柄類型OCI_HTYPE_SESSION,屬性類型 OCI_ATTR_USERNAME
鏈接數據庫用戶密碼:
句柄類型OCI_HTYPE_SESSION,屬性類型 OCI_ATTR_PASSWORD
事務:
句柄類型OCI_HTYPE_SVCCTX,屬性類型 OCI_ATTR_SESSION
eg:設置用戶名和密碼
char username[20],passwd[20];
strcpy(username,」tiger」)
strcpy(passwd,」cotton」)
swResult = OCIAttrSet(usrhp, OCI_HTYPE_SESSION, (text*) username, strlen(username),
OCI_ATTR_USERNAME, errhp);
if(swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
return FALSE;
swResult = OCIAttrSet(usrhp, OCI_HTYPE_SESSION, (text*) passwd, strlen(passwd),
OCI_ATTR_PASSWORD, errhp);
if(swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
return FALSE;
sword OCIAttrGet(
dvoid *trgthndlp, // 需讀取的句柄名
ub4 trghndltyp, //句柄類型
dvoid *attributep, //讀取的屬性名
ub4 *sizep, //屬性值長度
ub4 attrtype, //屬性類型
OCIError *errhp //錯誤句柄
)
四:鏈接/斷開服務器
多用戶方式鏈接:
sword OCIServerAttach(
OCIServer *srvhp,// 未初始化的服務器句柄
OCIError *errhp,
CONST text *dblink,//服務器SID
sb4 dblink_len,
ub4 mode //=OCI_DEFAULT, 系統環境將設爲阻塞方式
);
多用戶方式斷開:
sword OCIServerDetach (
OCIServer *srvhp,
OCIError *errhp,
ub4 mode //OCI_DEFAULT
);
五:開始/結束一個會話
sword OCISessionBegin (
OCISvcCtx *svchp, //服務 環境句柄
OCIError *errhp,
OCISession *usrhp, //用戶會話句柄
ub4 credt, //認證類型
ub4 mode //操做模式
);
認證類型:
OCI_CRED_RDBMS: 用數據庫用戶名和密碼進行認證,則先要設置OCI_ATTR_USERNAME和OCI_ATTR_PASSWORD屬性
OCI_CRED_EXT: 外部認證,不須要設置用戶和密碼
OCI_DEFAULT:用戶會話環境只能被指定的服務器環境句柄所設置
OCI_SYSDBA:用戶 要具備sysdba權限
OCI_SYSOPER:用戶要具備sysoper權限
sword OCISessionEnd (
OCISvcCtx *svchp,
OCIError *errhp,
OCISession *usrhp,
ub4 mode );
六:讀取錯誤信息
sword OCIErrorGet (
dvoid *hndlp, // 錯誤句柄
ub4 recordno,//從那裏讀取錯誤記錄,從1開始
text *sqlstate,//已取消,=NULL
sb4 *errcodep, //錯誤號
text *bufp, //錯誤內容
ub4 bufsiz, //bufp長度
ub4 type //傳遞的錯誤句柄類型 //=OCI_HTYPE_ERROR錯誤句柄 //=OCI_HTYPE_ENV: 環境句柄
);
eg:
ub4 ub4RecordNo = 1;
OCIError* hError
sb4 sb4ErrorCode;
char sErrorMsg[1024];
if (OCIErrorGet(hError, ub4RecordNo++, NULL, &sb4ErrorCode, (OraText*) sErrorMsg, sizeof(sErrorMsg), OCI_HTYPE_ERROR) == OCI_SUCCESS)
printf(「error msg:%s\n」, sErrorMsg);
七:準備SQL語句
sword OCIStmtPrepare (
OCIStmt *stmtp,//語句句柄
OCIError *errhp,
CONST text *stmt, //SQL語句
ub4 stmt_len, //語句長度
ub4 language, //語句的語法格式=OCI_NTV_SYNTAX
ub4 mode //=OCI_DEFAULT
);
eg:
char sSQL[1024];
sprintf(sSQL, 「select table_name from user_tables」);
swResult = OCIStmtPrepare(stmtp errhp, (CONST OraText*)sSQL, strlen(sSQL), OCI_NTV_SYNTAX, OCI_DEFAULT);
if(swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
return FALSE;
八:綁定輸入參數
OCIBindByName()----------------------按名綁定
OCIBindByPos()------------------------按位置綁定,建議通常按此方式綁定
OCIBindArrayOfStruct() -------------數組綁定,通常用於批量操做
OCIBindDynamic() Sets additional attributes after bind with OCI_DATA_AT_EXEC mode
OCIBindObject() Set additional attributes for bind of named data type
注: OCIBindArrayOfStruct 必須先用OCIBindByPos初始化,而後在OCIBindArrayOfStruct中定義每一個參數所跳過的字節數。
sword OCIBindByName (
OCIStmt *stmtp, // 語句句柄
OCIBind **bindpp,//結合句柄,=NULL
OCIError *errhp,
CONST text *placeholder,//佔位符名稱
sb4 placeh_len, // 佔位符長度
dvoid *valuep, //要替換的值的地址
sb4 value_sz, // 要替換的值的最大字節數
ub2 dty, //綁定的類型
dvoid *indp, //指示符變量指針(sb2類型),單條綁定時爲NULL,
ub2 *alenp, // 說明執行先後被結合的數組變量中各元素數據實際的長度,單條綁定時爲NULL
ub2 *rcodep,// 列級返回碼數據指針,單條綁定時爲NULL
ub4 maxarr_len, //最多 的記錄數,若是是單條綁定,則爲0
ub4 *curelep, //實際的記錄數,單 條綁定則爲NULL
ub4 mode //=OCI_DEFAULT
);
sword OCIBindByPos (
OCIStmt *stmtp,
OCIBind **bindpp,
OCIError *errhp,
ub4 position,// 綁 定的位置
dvoid *valuep,
sb4 value_sz,
ub2 dty,
dvoid *indp,
ub2 *alenp,
ub2 *rcodep,
ub4 maxarr_len,
ub4 *curelep,
ub4 mode );
sword OCIBindArrayOfStruct (
OCIBind *bindp,//綁定的結構句柄,由OCIBindByPos定義
OCIError *errhp,
ub4 pvskip, //下一列跳過的字節數
ub4 indskip,// 下一個指示器或數組跳過的字節數
ub4 alskip, //下一個實際值跳過的字節數
ub4 rcskip //下一個列級返回值跳過的字節數
);
九:定義輸出變量
OCIDefineArrayOfStruct() Set additional attributes for static array define
OCIDefineByPos() Define an output variable association
OCIDefineDynamic() Sets additional attributes for define in OCI_DYNAMIC_FETCH mode
OCIDefineObject() Set additional attributes for define of named data type
sword OCIDefineByPos (
OCIStmt *stmtp, //語句句柄
OCIDefine **defnpp,// 定義句柄—用於數組變量
OCIError *errhp,
ub4 position,// 位置序號(從1 開始)
dvoid *valuep, //輸出的變量名
sb4 value_sz, // 變量長度
ub2 dty, //數據類型
dvoid *indp, // 指示器變量/指示器變量數組,若是此字段可能存在空值,則要指示器變量,不然單條處理時爲NULL
ub2 *rlenp, // 提取的數據長度
ub2 *rcodep, //列級返回碼數組指針
ub4 mode //OCI_DEFAULT
);
sword OCIDefineArrayOfStruct (
OCIDefine *defnp,// 由OCIDefineByPos定義的句柄
OCIError *errhp,
ub4 pvskip, // 下一列跳過的字節數,通常就是結構的大小
ub4 indskip,//下一個指示器或結構 跳過的字節數,=0
ub4 rlskip, //下一個實際值跳過的字節數,=0
ub4 rcskip // 下一個列列級返回值跳過的字節數,=0
);
sword OCIDefineObject (
OCIDefine *defnp,
OCIError *errhp,
CONST OCIType *type,
dvoid **pgvpp,
ub4 *pvszsp,
dvoid **indpp,
ub4 *indszp
);
eg:
單條查詢
sql: select username,age from student where username=:p1;
若是此字段有可能有空值,則
hDefine = NULL;
swResult = OCIDefineByPos(stmtp &hDefine, errhp, 1, tstd.username, sizeof(tstd.username), SQLT_CHR, & sb2aInd[0], NULL, NULL, OCI_DEFAULT);
若是此字段沒有空值,則
hDefine = NULL;
swResult = OCIDefineByPos(stmtp &hDefine, errhp, 1, tstd.username, sizeof(tstd.username), SQLT_CHR, NULL, NULL, NULL, OCI_DEFAULT);
批量查詢
select username,age from student where age>;30;
hDefine = NULL;
swResult = OCIDefineByPos(stmtp, &hDefine, errhp, 1, &tstd[0].username,
sizeof(tstd[0].usenmae), SQLT_CHR, NULL, NULL, NULL, OCI_DEFAULT);
swResult = OCIDefineArrayOfStruct(hDefine, errhp, sizeof(tstd[0]), 0, 0, 0);
十:執行SQL語句
sword OCIStmtExecute (
OCISvcCtx *svchp, // 服務環境句柄
OCIStmt *stmtp, //語句句柄
OCIError *errhp,
ub4 iters, // **
ub4 rowoff, //**
CONST OCISnapshot *snap_in,
OCISnapshot *snap_out,
ub4 mode //**
);
注:
1. iters:對於select語句,它說明一次執行讀取到buffer中的記錄行數,若是不能肯定select語句所返回的行數,可將iters設置爲 0,而對於其餘的語句,iters表示這些語句的執行次數,此時iters不能爲0。
2. rowoff:在多行執行時,該參數表示從所結合的數據變量中的第幾條記錄開始執行(即記錄偏移量)。
3. mode:
=OCI_DEFAULT:default模式
=OCI_DESCRIBE_ONLY:描述模式,只返回選擇列表的描述信息,而不執行語句
=OCI_COMMIT_ON_SUCCESS:自動提交模式,當執行成功後,自動提交。
=OCI_EXACT_FETCH:精確提取模式。
=OCI_BATCH_ERRORS:批錯誤執行模式:用 於執行數組方式的操做,在此模式下,批量insert ,update,delete時,執行過程當中任何一條記錄錯誤不會致使整個 insert ,update,delete失敗,系統自動會收集錯誤信息,而在非批錯誤方式下,其中的任何一條記錄錯誤,將會致使整個操做失敗。
Eg:
執行一次
swResult = OCIStmtExecute(svchp, stmtp, errhp,1, 0, NULL, NULL, OCI_DEFAULT);
批量執行100次:
swResult = OCIStmtExecute(svchp, stmtp, errhp, 100, 0, NULL, NULL, OCI_DEFAULT);
十一:提取結果
sword OCIStmtFetch (
OCIStmt *stmtp,//語句句柄
OCIError *errhp,
ub4 nrows, //從當前位置處開始一次提取的記錄數,對於數據變量,可 以>;1,不然不能>;1
ub2 orientation,//提取 的方向:OCI_FETCH_NEXT
ub4 mode //OCI_DEFAULT
)
eg:
while ((swResult=OCIStmtFetch stmtp errhp,1,OCI_FETCH_NEXT,OCI_DEFAULT)) != OCI_NO_DATA)
{
……
}
十二:事務操做
開始一個事務
sword OCITransStart (
OCISvcCtx *svchp,
OCIError *errhp,
uword timeout, //**
ub4 flags );
注:
1. Timeout:
當flag=OCI_TRANS_RESUME:它表示還有多少秒事務將被激活 ,=OCI_TRANS_NEW: 事務響應的超時時間(秒)
2. Flags:指定一個新的事務仍是已有事務
=OCI_TRANS_NEW:定義一個新的事務
=OCI_TRANS_RESUME
準備一個事務:
sword OCITransPrepare (
OCISvcCtx *svchp,
OCIError *errhp,
ub4 flags );//OCI_DEFAULT
sword OCITransForget (
OCISvcCtx *svchp,
OCIError *errhp,
ub4 flags );//OCI_DEFAULT
斷開一個事務:
sword OCITransDetach (
OCISvcCtx *svchp,
OCIError *errhp,
ub4 flags );//OCI_DEFAULT
提交一個事務:
sword OCITransCommit (
OCISvcCtx *svchp, //服務環境句柄
OCIError *errhp,
ub4 flags ); //OCI_DEFAULT
回滾一個事務
sword OCITransRollback (
dvoid *svchp,
OCIError *errhp,
ub4 flags ); //OCI_DEFAULT
關於OCI編程的各個函數的參數詳細解釋能夠參考Oracle官網的在線手冊,很是好用。
參考地址:http://download.oracle.com/docs/cd/A91202_01/901_doc/appdev.901/a89857/toc.htm
6:介紹一下OCI須要注意的地方
一: 關於輸出變量定義:若是在語句執行前就知道select語句的選擇列表結構,則定義輸出操做可在調用 OCISTMTExecute前進行,若是查詢語句的參數爲用戶動態輸入的,則必須在執行後定義。
二:OCI函數返回值:
OCI_SUCCESS –函數執行成功 (=0)
OCI_SUCCESS_WITH_INFO – 執行成功,但有診斷消息返回,多是警告信息
OCI_NO_DATA—函數執行完成,但沒有其餘數據
OCI_ERROR—函數執行錯 誤
OCI_INVALID_HANDLE—傳遞給函數的參數爲無效句柄,或傳回的句柄無效
OCI_NEED_DATA—須要應用程序 提供運行時刻的數據
OCI_CONTINUE—回調函數返回代碼,說明回調函數須要OCI庫恢復其正常的處理操做
OCI_STILL_EXECUTING —服務環境創建在非阻塞模式,OCI函數調用正在執行中。
三: OCI鏈接有二種方式:Blocking(阻塞方式)和non_Blocking(非阻塞方式),阻塞方式就是當調用 OCI操做時,必須等到此OCI操 做完成後服務器才返回客戶端相應的信息,不論是成功仍是失敗。非阻塞方式是當客戶端提交OCI操做給服務器後,服務器當即返回 OCI_STILL_EXECUTING信息,而並不等待服務端的操做完成。 對於non- blocking方式,應用程序若收到一個OCI函數的返回值爲 OCI_STILL_EXECUTING時必須再次對每個OCI函數的返回值進行判 斷,判斷其成功與否。 可經過設置服務器屬性爲OCI_ATTR_NONBLOCKING_MODE來實現。系統默認方式爲阻塞模式。
四: OCI函數設置的模式有:
OCI_DEFUALT:使用OCI默認的環境
OCI_THREADED:線程環境下使用OCI
OCI_OBJECT:對象模式 //你們注意這個,當使用Orcale Spatial空間數據庫時須要加上次模式。
OCI_SHARED:共享模式
OCI_EVENTS
OCI_NO_UCB
OCI_ENV_NO_MUTEX:非互斥訪問模式
其中模式能夠用邏輯運算符進行迭加,將函數設置成多多種模式:如 mode=OCI_SHREADED| OCI_OBJECT
五: 當應用進程與服務器斷開鏈接時,程序沒有使用OCITransCommit()進行事務的提交,則全部活動的事務會自動回滾。
六: OCI重定義數據類型
typedef unsigned char ub1;
typedef signed char sb1;
typedef unsigned short ub2;
typedef signed short sb2;
typedef unsigned int ub4;
typedef signed int sb4;
typedef ub4 duword;
typedef sb4 dsword;
typedef dsword dword;
七: 在SQL語句準備後,能夠用OCIAttrSet(設置該語句的類型屬性OCI_ATTR_STMT_TYPE,之後可讀取語句屬性,根據屬性分別進行處理。
八: 批量綁定輸入和定義輸出參數:將數據存入一個靜態數據組中。一次執行能夠提交或讀取多行記錄值。
九:結合佔位符和指示器變量:
①佔位符:在程序中,一些SQL語句須要在程序運行時才能肯定它的語句數據,在設計時可用一個佔位符來代替,當程序運行 時,在它準備好語句後,必須爲每一個佔位符指定一個變量,即將佔位符與程序變量地址結合,執行時,Oracle就從這些變量中讀取數據,並將它們與SQL語 句一塊兒傳遞給Oracle服務器執行。OCI結合佔位符時,它將佔位符與程序變量關聯起來,並同時要指出程序變量的數據類型和數據長度。
如:select * from test where name=:p1 and age=:p2 (:p1和:p2爲佔位符 )
②指示器變量:因爲在Oracle中,列值能夠爲NULL,但在C語言中沒有NULL 值,爲了能使OCI程序表達NULL列值,OCI函數容許程序爲所執行語句中的結合變量同時關聯一個指示符變量或指示符變量數組,以說明所結合的佔位符是 否爲NULL或所讀取的列值是否爲NULL,以及所讀取的列值是否被截取。
除SQLT_NTY(SQL Named DataType)外,指示符變量或指示符變量數組的數據類型爲sb2,其值說明:
做爲輸入變量時:(如insert ,update語句中)
=-1:OCI程序將NULL賦給Oracle表的列,忽略佔位符結合的程序變量值
>;=0:應用程序將程序變量值賦給指定列
做 爲輸出變量時:(如select語句中)
=-2:所讀取的列數據長度大於程序變量的長度,則被截取。
=-1:所讀取的值爲 NULL,輸出變量的值不會被改變。
=0:數據被完整讀入到指定的程序變量中
>0:所讀取的列數據長度大於程序變量的長度,則被截 取,指示符變量值爲所讀取數據被截取前的實際長度
終於寫完了,基本上就這麼多了,但願對你有幫助。
這裏不能添加附加,直接貼代碼的話,不是個人風格。下面給你們介紹能夠學習和直接拿來用的代碼地址:
①一個簡單的鏈接Oracle數據庫的代碼,詳細的說明了鏈接Oracle數據庫的步驟(比較簡單,沒有輸入與輸出)
參考地址:http://blog.csdn.net/sherlockhua/article/details/4353531 (適合初學者)
②我寫的一個簡單的OCI接口類,能批量讀取和插入數據的類,裏面涉及了一些比較經常使用函數的用法,值得看一下
參考地址:http://www.pudn.com/downloads371/sourcecode/database/detail1607043.html
③關於Oracle空間數據庫的讀取與寫入 (比較全面,也比較複雜)
參考地址:http://www.codesky.net/article/doc/200406/20040619864916.htm