Pro*C? OCI
OCCI? 這三種都是C/C++訪問數據庫的手段。
Pro*C:
內嵌SQL,預編譯后把內嵌SQL處理為ORACLE標準運行庫的調用,然后再象編譯一般的C程序一樣進行編譯、連接、運行。
1.proc XXX.pc
2.gcc/g++ XXX.c –lclntsh
(PRO*C的預編譯,也可直接MAKEFILE搞定)
OCI/OCCI:
oracle提供的訪問oracle數據庫的API,比較繁瑣,但是完全符合C/C++語言的訪問流程,清晰,便于理解,調試。
OCI:Oracle Call Interface ;(C語言實現)
OCCI:Oracle C++ Call Interface;(C++語言實現)
OCI使用步驟大致介紹
OCI(Oracle Call
Inte***ce)是由頭文件和庫函數等組成的一套Oracle數據庫應用程序編程接口工具,OCI程序實質上就是用高級語言寫的程序,其特點是內部含有對OCI子函數庫的調用。
OCI程序對開發環境的要求相對較低,只要有C語言的OCI開發工具包和C編譯器就可以,程序設計相比PRO*C復雜了點。
1、創建和初始化OCI環境
首先要在源程序中包含OCI頭文件:#include
OCI環境即OCI函數的工作環境,在調用其他函數之前必須先調用OCIInitialize()和OCIEnvInit()函數創建和初始化OCI環境,其他OCI函數要在這個環境中才能執行。
先定義變量:
OCIEnv**?? m_envhp;
OCIError*? m_errhp;
OCIServer* m_srvhp;
OCISvcCtx* m_svchp;
OCIStmt *? m_stmthp;
OCIInitialize(
(ub4) OCI_DEFAULT,
(dvoid *)0,
(dvoid * (*)(dvoid *, size_t))0,
(dvoid * (*)(dvoid *, dvoid *, size_t))0,
(void (*)(dvoid *, dvoid *))0
);
OCIEnvInit(
(OCIEnv **)&m_envhp,
OCI_DEFAULT, (size_t)0,
(dvoid **)0
);
其中m_envhp為輸出參數,是一個指向OCI環境句柄的指針,OCI_DEFAULT
是OCI環境的初始化模式。OCIEnvInit()函數中的size_t類型變量為分配給用戶的內存數量,dvoid
**類型變量指向用戶的內存區域,該區域的大小等于size_t類型變量。
OCI函數中,大量使用OCI定義的數據類型和宏,其定義可參考$ORACLE_HOME/rdbms/demo目錄下的oci.h頭文件。
2、申請句柄
句柄是指向OCI庫所分配的內存區域的指針,該內存區域中的數據由OCI庫維護,應用程序可通過句柄訪問其中的數據。下面是應用程序中最常用的幾個句柄:
OCIHandleAlloc(
(dvoid *)m_envhp,
(dvoid **)&m_errhp,
OCI_HTYPE_ERROR,
(size_t)0,
(dvoid **)0
);
OCIHandleAlloc(
(dvoid *)m_envhp,
(dvoid **)&m_srvhp,
OCI_HTYPE_SERVER,
(size_t)0,
(dvoid **)0
);
OCIHandleAlloc(
(dvoid *)m_envhp,
(dvoid **)&m_svchp,
OCI_HTYPE_SVCCTX,
(size_t) 0,
(dvoid **)0
);
OCIHandleAlloc(
(dvoid *)m_envhp,
(dvoid **)&m_stmthp,
OCI_HTYPE_STMT,
(size_t)0,
(dvoid **)0
);
其中m_errhp為新申請的句柄,m_envhp為它的父環境句柄,OCI_HTYPE_ERROR為句柄類型,表示這是一個錯誤報告句柄,OCI_HTYPE_SERVER表示服務器句柄,OCI_HTYPE_SVCCTX表示服務環境句柄,OCI_HTYPE_STMT表示語句句柄。
存儲在句柄中的數據稱為句柄屬性,所有OCI句柄都具有屬性,可以調用OCIAttrGet()和OCIAttrSet()函數來讀取、設置句柄屬性。
3、連接服務器建立會話
首先調用
OCIServerAttach(m_srvhp, m_errhp, (text
*)"",
strlen(""), OCI_DEFAULT);
函數建立與指定服務器的連接,text
*類型變量為空,表示連接默認數據庫服務,OCI_DEFAULT表示應用程序的操作模式為阻塞模式,在這種方式下,只有當OCI調用完成后才將控制權返回給客戶端應用程序。
然后調用
OCILogon(m_envhp,m_errhp, &m_svchp,
(text*)m_szUser,strlen(m_szUser), (text*)m_szPassword,
strlen(m_szPassword), (text*)m_szDbName, strlen(m_szDbName));
建立數據庫會話。此函數隱含申請服務器句柄和用戶會話句柄,登錄后,句柄是只讀的,不能再設置句柄屬性。
4、執行SQL語句并處理數據
將要執行的SQL語句copy到szSqlStr字符串中:
snprintf( szSqlStr, sizeof(szSqlStr), "select
PASSWORD from USERS where USERNAME=’chen’
");
執行下列語句:
OCIStmtPrepare(m_stmthp, m_errhp, (text*)szSqlStr, (ub4)
strlen(szSqlStr), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT);
//準備SQL語句
OCIDefine *defnp0 = (OCIDefine *) 0; //定義輸出變量
OCIDefineByPos( m_stmthp, &defnp0, m_errhp, 1,
(dvoid *)szUSERNAME, 100, SQLT_STR, (dvoid *) 0, (ub2 *)0, (ub2
*)0, OCI_DEFAULT); //綁定變量
OCIStmtExecute( m_svchp, m_stmthp, m_errhp, (ub4) 1, (ub4) 0,
(OCISnapshot *) NULL,(OCISnapshot *) NULL, (ub4) OCI_DEFAULT);
//執行SQL語句
5、結束會話斷開數據庫連接 OCILogoff( m_svchp,
m_errhp );
6、斷開與數據源的連接,釋放句柄
OCIServerDetach( m_srvhp, m_errhp, OCI_DEFAULT ); //斷開與數據源的連接
OCIHandleFree((dvoid *) m_stmthp, OCI_HTYPE_STMT); //釋放句柄
OCIHandleFree((dvoid *) m_svchp, OCI_HTYPE_SVCCTX);
OCIHandleFree((dvoid *) m_srvhp, OCI_HTYPE_SERVER);
OCIHandleFree((dvoid *) m_errhp, OCI_HTYPE_ERROR)
3.7生成可執行文件(兩種方法)
(1)同普通的C程序:
gcc -o exampled –I.
–I$(ORACLE_HOME)/precomp/public example.c
(2)利用Oracle自帶的Make文件:
首先將$ORACLE_HOME/rdbms/demo/demo_rdbms.mk文件copy到OCI源程序所在的目錄,將源文件編譯為目標文件:
#gcc –c example.o -I$(ORACLE_HOME)/rdbms/demo
-I$(ORACLE_HOME)/network/public -I$(ORACLE_HOME)/rdbms/public/
example.c
然后用命令:#make -f demo_rdbms.mk build OBJ*=**ample.o
EXE=exampled,exampled就為生成的可執行文件
OCI常用函數說明:
一、初始化OCI程序環境。
OCI8使用OCIInitialize函數來初始化OCI。這是使用OCI8與數據庫建立會話必須的一步;同時,必須是第一步。如果成功,則返回0。
函數原型:sword OCIInitialize (ub4 mode,CONST dvoid *ctxp,CONST dvoid
*(*malocfp) (/* dvoid *ctxp,size_t size _* /),
CONST dvoid *(*ralocfp)(/*_ dvoid *ctxp,dvoid *memptr,size_t
newsize _* /),
CONST void (*mfreefp)(/*_ dvoid *ctxp,dvoid *memptr _* /))
參數說明:
mode——詳細說明OCI初始化(Initialize)模式(mode)。它的取值如下:
OCI_DEFAULT——缺省模式;
OCI_THREADED——多線程模式;在該模式下,各并發處理中不為用戶所見的內在數據結構受各自線程的保護,而不受別的線程干擾;
OCI_OBJECT——使用目標特性;
OCI_SHARED——使用共享內存;
OCI_EVENTS——
Mode參數可以擁有多個值,以“|”符號分隔各取值項。
*Ctxp——用戶定義的內存回調程序;默認為0
*(*malocfp)——用戶定義的內存分配程序;默認為0
*(*ralocfp)——重新分配內存程序;默認為0
*memptr 是指向內存塊的指針;
*mfreefp——用戶定義的內存釋放程序;默認為0
該函數使用舉例如下:
OCIInitialize((ub4) OCI_THREADED | OCI_OBJECT,
(dvoid *)0,(dvoid *(*)(dvoid *, size_t)) 0,
(dvoid * (*)(dvoid *,dvoid *,size_t))0,
(void (*)(dvoid *,dvoid *)) 0 )
注意!OCIEnvCreate() 可以代替OCIInitialize() 和OCIEnvInit()
二、 初始化OCI環境句柄。
在初始化OCI程序環境以后,使用OCIEnvInit來初始化OCI的環境句柄,該函數成功返回0。
函數原型:sword OCIEnvInit(OCIEnv **envhpp,
ub4 mode,
size_t xtramemsz,
dvoid **usrmempp )
參數說明:
**envhpp——指向環境句柄的指針;
mode——指定初始化環境句柄的模式,其取值如下:
OCI_DEFAULT——缺省模式;在缺省模式下,OCI庫始終互斥各環境句柄;
OCI_NO_MUTEX——非互斥模式;在該模式下,OCI庫各環境句柄并不互斥,所有的掉用都使用同一個環境句柄,并且只能有一個環境句柄起作用。
OCI_ENV_NO_UCB——禁止回滾模式;該模式用以禁止在環境句柄初始化過程中的動態CALL_BACK函數掉用;
Xtramemsz——指定在該環境句柄生存期內分配內存的數量;
**usrmempp——指向Xtramemsz參數的指針;usermempp參數是函數返回值;
該函數使用舉例如下:
應用例子:OCIEnvInit((OCIEnv **) envhp,
(ub4) OCI_DEFAULT,
(size_t) 0,(dvoid **) 0)
三、 分配各OCI句柄。
一個OCI連接在建立前,還需要將所需要的句柄一一分配成功,在OCI8里,使用函數OCIHandleAlloc來分配各句柄,成功返回0。
函數原型:sword OCIHandleAlloc(CONST dvoid *parenth,
dvoid **hndlpp,
ub4 type,
size_t xtramem_sz,
dvoid **usrmempp )
參數說明:
*parenth——已初始化后的環境句柄;
**hndlpp——函數執行成功后,返回的一個OCI句柄;該返回值的具體含義由type參數來決定;
type——參數hndlpp的返回值的類型;其常用取值如下:
OCI_HTYPE_SVCCTX——返回一個服務類型的句柄;
OCI_HTYPE_ERROR——返回一個錯誤類型的句柄;
OCI_HTYPE_SESSION——返回一個會話類型的句柄;
OCI_HTYPE_SERVER——返回一個服務器類型的句柄;
OCI_HTYPE_STMT——返回一個陳述類型的句柄;
其中,陳述類型的句柄是在創建與數據庫會話成功后,將要對數據庫進行操作時分配的,其余類型的句柄是在環境句柄初始化后分配的;
xtramem_sz——指定在該句柄生存期內分配內存的數量;
**usrmempp——指向xtramem_sz參數的指針,由函數返回;
該函數使用舉例如下:OCIHandleAlloc((dvoid *) *envhp,
(dvoid **) errhp,
(ub4) OCI_HTYPE_ERROR,
(size_t) 0,
(dvoid **) 0)
四、
為OCI操作數據源創建存儲路徑 (以給定的方式設置服務器連接指針的參數)。
分配各OCI句柄后,還需要做的工作是為OCI操作數據源創建存儲路徑,并將各項參數設置到相應的句柄中,這項工作由函數OCIServerAttach和OCIAttrSet來實現。成功,返回0。
函數原型:sword OCIServerAttach(OCIServer *srvhp,
OCIError *errhp,
CONST text *dblink,
sb4 dblink_len,
ub4 mode )
參數說明:
*srvhp——已分配成功的服務器句柄;
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
*dblink——登陸數據庫的實例名;
dblink_len——參數*dblink字符串的長度;
mode——指定不同操作的模式。現在只有一種模式可選:OCI_DEFAULT。
該函數使用舉例如下:OCIServerAttach(srvhp, errhp,
(text *) cstring,
(sb4) strlen((char *)cstring), (ub4) OCI_DEFAULT))
函數原型:sword OCIAttrGet (CONST dvoid *trgthndlp,
ub4 trghndltyp,
dvoid *attributep,
ub4 *sizep,
ub4 attrtype,
OCIError *errhp )
參數說明:
*trgthndlp——需要設置的句柄,該句柄在這之前已分配成功;該參數由trghndltyp參數決定;
trghndltyp——參數trgthndlp的類型,其取值參見OCIHandleAlloc函數說明中的type參數說明;
*attributep——設置參數trgthndlp的值;
*sizep——attributep參數指向的字符串長度;
attrtype——參數attributep的類型;其取值如下:
OCI_ATTR_SERVER——服務器類型;
OCI_ATTR_USERNAME——用戶名類型
OCI_ATTR_PASSWORD——用戶密碼類型
OCI_ATTR_SESSION——會話類型;
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
該函數使用舉例如下:OCIAttrSet((dvoid *) svchp,
(ub4) OCI_HTYPE_SVCCTX,
(dvoid *) srvhp,
(ub4) 0,
(ub4) OCI_ATTR_SERVER,
errhp))
(注:此時該函數的意思是將服務器句柄設置到服務句柄中,其類型為服務器類型)
說明:在登陸數據庫前以給定的方式設置服務器連接指針的參數時,attrtype參數的所有類型都需要設置到服務句柄中。設置的步驟為:先將服務器句柄設置到服務句柄中,然后將用戶名、密碼設置到會話句柄中,在調用OCISessionBegin函數成功后,再將會話句柄設置到服務句柄中。
五、 創建并開始與數據庫的會話
創建和開始與數據庫的會話使用函數OCISessionBegin來實現,其目的是建立與數據庫的會話連接;函數成功,返回0。
函數原型:sword OCISessionBegin (OCISvcCtx *svchp,
OCIError *errhp,
OCISession *authp,
ub4 credt,
ub4 mode))
參數說明:
*svchp——已分配并設置成功的服務句柄;
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
*authp——已分配并設置了用戶名、密碼的會話句柄;
credt——建立用戶會話的類型;其取值如下:
OCI_CRED_RDBMS——需要使用用戶名和密碼來建立會話;
OCI_CRED_EXT——不需要使用用戶名和密碼來建立會話;
mode——操作的模式;其取值如下:
OCI_DEFAULT——缺省模式;在該模式下只支持一個會話句柄;
OCI_MIGRATE——移動會話模式;在該模式下,新的會話連接會以不同的會話句柄返回;使用該模式創建新的會話時,必須已存在一個不可移動會話模式的會話連接。也就是說,一個移動會話模式的會話連接必須有一個不可移動模式的連接作為父連接;
OCI_SYSDBA——在該模式下,會鑒別用戶是否以SYSDBA形式對數據庫進行訪問;
OCI_SYSOPER——在該模式下,會鑒別用戶是否以SYSOPER形式對數據庫進行訪問;
OCI_PRELIM_AUTH——這種模式和OCI_SYSDBA、OCI_SYSOPER一起使用,作為某些訪問任務的鑒別;
該函數使用舉例如下:OCISessionBegin(svchp,
errhp,
authp,
OCI_CRED_RDBMS,
OCI_DEFAULT)
六、
取得errhp承載的錯誤原因。
若某函數執行出錯,則可以使用函數OCIErrorGet來取得錯誤原因,從而能得到某些提示。
函數原型:sword OCIErrorGet (dvoid *hndlp,
ub4 recordno,
text *sqlstate,
sb4 *errcodep,
text *bufp,
ub4 bufsiz,
ub4 type )
參數說明:
*hndlp——錯誤類型句柄errhp;
recordno——錯誤查找的原始位置,從1開始,其缺省值為1;
*sqlstate——OCI8不支持,缺省值為NULL;
*errcodep——ORACLE錯誤返回代碼,由函數返回;初始值可以為(sb4)0;
*bufp——錯誤信息提示,由函數以字符串形式返回;
bufsiz——bufp參數原始字符串長度;
type——句柄類型;其取值為OCI_HTYPE_ERR或著為OCI_HTYPE_ENV;缺省值為OCI_HTYPE_ERR;
該函數使用舉例如下:OCIErrorGet((dvoid *) errhp,
(ub4) 1,
(text *) NULL,
&errcode,
(text *)msgbuf,
(ub4) sizeof(msgbuf),
(ub4) OCI_HTYPE_ERROR)
七、 準備執行
用戶定義的SQL或PL/SQL陳述語句。
在執行SQL或PL/SQL語句前,需要對該語句執行分析、出錯檢查,并和陳述句柄棒定起來,使用函數OCIStmtPrepare來進行這一系列操作。該函數在執行陳述語句前必須使用;成功,返回0;
函數原型:sword OCIStmtPrepare ( OCIStmt *stmtp,
OCIError *errhp,
CONST text *stmt,
ub4 stmt_len,
ub4 language,
ub4 mode)
參數說明:
*stmtp——已分配成功的陳述句柄;
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
*stmt——用戶定義的需要執行的SQL或PL/SQL陳述語句;
stmt_len——用戶定義的需要執行的陳述語句的長度;該參數的值不能為0;
language——語法模式;聲明是本地語法,還是V7模式語法。其取值如下:
OCI_V7_SYNTAX——ORACLE的V7分析語法;
OCI_NTV_SYNTAX——語法依賴于服務器的版本;
mode——模式;其缺省值為OCI_DEFAULT;
該函數使用舉例如下:OCIStmtPrepare(stmthp,
errhp,
sqlcommand,
(ub4)strlen((char *)sqlcommand),
(ub4) OCI_NTV_SYNTAX,
(ub4) OCI_DEFAULT)
八、 定義輸出變量。
OCI執行陳述語句后,將所選擇的變量值返回輸出,此時需有用戶定義的地址空間來容納這些返回值。使用函數OCIDefineByPos通過在陳述語句中標志某變量在用戶定義的變量集合中的位置來定義變量;若該函數執行成功,返回0。
函數原型:sword OCIDefineByPos (OCIStmt *stmtp,
OCIDefine **defnpp,
OCIError *errhp,
ub4 position,
dvoid *valuep,
sb4 value_sz,
ub2 dty,
dvoid *indp,
ub2 *rlenp,
ub2 *rcodep,
ub4 mode )
參數說明:
*stmtp——用以進行查詢的陳述語句句柄;該句柄必須是已經分配成功的句柄;
**defnpp——用戶定義的變量集合的指針;該參數指針從下標0開始,依次遞增一個數組單元;
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
position——需要定義的變量在定義句柄的列表中的位置,從1開始;例如:
SELECT empno, ssn, mgrno FROM employees;
則empno的position值為1,ssn的position的值為2,mgrno的position值為3;以此類推。
*valuep——需要定義的變量的在執行成功后的存儲地址;如果提取出來的數據有多項,則該參數可以使用數組;
value_sz——valuep參數的指向的存儲地址空間的長度;
dty——需要定義的變量的數據類型;SQLT_STR表示該變量是個字符串變量;SQLT_INT則表示該變量是個整型變量;
*indp——變量或數組指示器,默認為0;
*rlenp——變量或數組長度指示器,默認為0;
*rcodep——即將提取的變量的值指示器,默認為0;
mode——變量提取模式。其取值為OCI_DEFAULT或OCI_DYNAMIC_FETCH;OCI_DYNAMIC_FETCH用于在提取資料過程中,需要動態資料的時候,此時必須用CIDefineDynamic函數建立一個回調函數用以提取數據;這種情況下,valuep和value_sz參數可以忽略;
該函數使用舉例如下:OCIDefineByPos(stmthp, &dfnhp[4],
errhp, (ub4) 5,
(dvoid *) &No[0],
(sb4) sizeof(No[0]),
(ub2) SQLT_INT,
(dvoid *) 0,
(ub2 *) 0,
(ub2 *) 0,
(ub4) OCI_DEFAULT)
補充說明:如果輸出變量是多行資料,則valuep參數應該為一個用戶定義了大小的靜態數組的初始地址,其大小為輸出變量的行數與該變量自身大小的乘積。此時,在函數后面還需要使用另一個函數OCIDefineArrayOfStruct來定義該數組。函數OCIDefineArrayOfStruct說明如下:
函數原形:sword OCIDefineArrayOfStruct(OCIDefine *defnp,
OCIError *errhp,
ub4 pvskip,
ub4 indskip,
ub4 rlskip,
ub4 rcskip )
參數說明:
*defnp——從函數OCIDefineByPos返回的對應該變量的定義句柄,對應于OCIDefineByPos函數的第二項參數defnpp;
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
pvskip——從本條記錄中該變量的存儲地址的到下條記錄中該變量的存儲地址之間的大小;也就是定義的一條記錄的存儲空間的大小;
indskip——默認為0;
rlskip——默認為0;
rcskip——默認為0;
該函數使用舉例說明如下(對應于函數OCIDefineByPos的例子):
OCIDefineArrayOfStruct(dfnhp[4],
errhp,
sizeof(No[0]),
0,0,0)
九、 定義輸入變量
OCI在執行陳述語句時,有時需要向該語句傳遞輸入值,OCI8通過函數OCIBindByPos或OCIBindByName來實現該功能,OCIBindByPos將需要輸入的變量與與其對應的參數值的位置綁定起來,從而實現向陳述語句中傳遞值的效果,而OCIBindByName則是通過綁定相應的變量名稱來實現輸入值的傳遞。
函數原型: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 )
參數說明:
*stmtp——用以進行查詢的陳述語句句柄;該句柄必須是已經分配成功的句柄;
**bindpp——用戶定義的傳入值集合的指針;該參數指針從下標0開始,依次遞增一個數組單元;
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
position——需要綁定的該變量在陳述語句的列表中的位置,從1開始,依次遞增;
*valuep——需要綁定的傳入值的存儲地址;
value_sz——valuep參數的指向的存儲地址空間的長度;
dty——需要綁定的變量的數據類型;SQLT_STR表示該變量是個字符串變量;SQLT_INT則表示該變量是個整型變量;
*indp——變量或數組指示器,默認為0;
*alenp——變量或數組長度指示器,默認為0;
*rcodep——即將提取的變量的值指示器,默認為0;
maxarr_len——dyt參數的最大可能取值的數目,在非PL/SQL語句中該差數無效果;默認值為0;
*curelep——對應與maxarr_len,表示dyt參數取值的實際數目;默認值為0;
mode——變量提取模式。其取值為OCI_DEFAULT或OCI_DATA_AT_EXEC;當使用OCI_DATA_AT_EXEC時,value_sz表示在該陳述語句執行過程中可以使用的傳入的該項值的最大存儲長度,此時需要動態綁定該傳入值;一般來說,mode的取值都為OCI_DEFAULT;
該函數使用舉例如下:OCIBindByPos(stmthp, &bndhp[3],
errhp, (ub4) 4,
(dvoid *) register_number,
(sb4) nLen, SQLT_STR,
(dvoid *) 0, (ub2 *)0,
(ub2 *)0,
(ub4) 0, (ub4 *) 0,
(ub4) OCI_DEFAULT)
函數原型:sword OCIBindByName ( OCIStmt *stmtp,
OCIBind **bindpp,
OCIError *errhp,
CONST text *placeholder,
sb4 placeh_len,
dvoid *valuep,
sb4 value_sz,
ub2 dty,
dvoid *indp,
ub2 *alenp,
ub2 *rcodep,
ub4 maxarr_len,
ub4 *curelep,
ub4 mode )
參數說明:
*stmtp——用以進行查詢的陳述語句句柄;該句柄必須是已經分配成功的句柄;
**bindpp——用戶定義的傳入值集合的指針;該參數指針從下標0開始,依次遞增一個數組單元;
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
*placeholder——需要綁定的該變量在陳述語句中的占位符;
placeh_len——palceholder參數的長度;
*valuep——指向需要綁定的該變量的傳入值的地址;
value_sz——valuep參數存儲的變量值的位組長度;
dty——需要綁定的變量的數據類型;SQLT_STR表示該變量是個字符串變量;SQLT_INT則表示該變量是個整型變量;
*indp——變量或數組指示器,默認為0;
*alenp——變量或數組長度指示器,默認為0;
*rcodep——即將提取的變量的值指示器,默認為0;
maxarr_len——dyt參數的最大可能取值的數目,在非PL/SQL語句中該差數無效果;默認值為0;
*curelep——對應與maxarr_len,表示dyt參數取值的實際數目;默認值為0;
mode——變量提取模式。其取值為OCI_DEFAULT或OCI_DATA_AT_EXEC;當使用OCI_DATA_AT_EXEC時,value_sz表示在該陳述語句執行過程中可以使用的傳入的該項值的最大存儲長度,此時需要動態綁定該傳入值;一般來說,mode的取值都為OCI_DEFAULT;
該函數使用舉例如下:OCIBindByName(stmthp, &bndhp[1],
errhp,
(text *) ":field1",
(sb4) strlen((char *)
":phone_number"),
(dvoid *) & to_field1,
(sb4) sizeof(phone_number),
SQLT_STR,
(dvoid *) 0, (ub2 *)0,
(ub2 *)0,(ub4) 0, (ub4 *) 0,
(ub4) OCI_DEFAULT)
補充說明:如果輸入變量是多行資料,則valuep參數應該為一個用戶定義了大小的靜態數組的初始地址,其大小為輸入變量的行數與該變量自身大小的乘積。此時,在函數后面還需要使用另一個函數OCIBindArrayOfStruct來定義該數組。函數OCIBindArrayOfStruct說明如下:
函數原型:sword OCIBindArrayOfStruct ( OCIBind *bindp,
OCIError *errhp,
ub4 pvskip,
ub4 indskip,
ub4 alskip,
ub4 rcskip )
參數說明:
*bindp——從函數OCIBindByPos或OCIBindByName返回的對應該變量的綁定句柄,對應于函數OCIBindByPos或OCIBindByName的第二項參數bindpp;
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
pvskip——從本條記錄中該變量的存儲地址的到下條記錄中該變量的存儲地址之間的大小;也就是定義的一條記錄的存儲空間的大小;
indskip——默認為0;
rlskip——默認為0;
rcskip——默認為0;
該函數使用舉例如下:OCIBindArrayOfStruct(bndhp[N],
errhp,
sizeof(record_array[0]),
indsk[N],
rlsk[N],
rcsk[N])
十、 執行陳述語句。
在執行語句分析完成,并且變量定義或綁定完成后,便可以執行該陳述句柄,從而實現陳述語句中的SQL語句能完成的功能。使用函數OCIStmtExecute來執行該陳述句柄。執行成功,返回0;
函數原型:sword OCIStmtExecute ( OCISvcCtx *svchp,
OCIStmt *stmtp,
OCIError *errhp,
ub4 iters,
ub4 rowoff,
CONST OCISnapshot *snap_in,
OCISnapshot *snap_out,
ub4 mode)
參數說明:
*svchp——已分配并設置成功的服務句柄;
*stmtp——指向需要執行的陳述語句的句柄;
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
iters——對于非選擇語句來說,該函數執行次數等于iters減去rowoff的值;對于選擇語句來說,如果iters不為0,則該函數在執行前必須有定義句柄(即需要定義位址空間來存儲select出來的變量值),而函數會預先提取出多于iters條記錄(如果可提取記錄條數大于iters的話),將其中iters條正式提取出來;如果事先并不知道有多少條記錄會被提取,則將iters的值置為0;在非選擇語句中,若iters的值為0,則函數返回錯誤;
rowoff——函數執行時,輸入變量在綁定的變量數組的開始位置。用于多行記錄的修改或插入、刪除;比如,定義的綁定變量為array[100],執行該函數時,iters的值為50,rowoff的值為10,則表示從array[10]開始提取傳入值,而執行的次數則是50-10
= 40(次);
*snap_in——可選參數。默認值為0;
*snap_out——可選參數。默認值為0;
mode——執行模式;有四種執行模式:
OCI_DEFAULT——缺省模式,在該模式下,總是隱式返回選擇選擇語句的有關描述信息;
OCI_DESCRIBE_ONLY——在該模式下,陳述句柄并不被執行,但是它會返回可提取記錄的條數;
OCI_COMMIT_ON_SUCCESS——在該模式下,如若函數執行成功,則當前的處理馬上會自動提交;
OCI_EXACT_FETCH——該模式用于當前程序很明確的清楚有多少條記錄會被提取出來;并且,使用該模式前必須要有定義句柄;
該函數的使用舉例如下:OCIStmtExecute(svchp, stmthp, errhp,
(ub4) nCount, (ub4) 0,
(CONST OCISnapshot*) 0,
(OCISnapshot*) 0,
(ub4) OCI_DEFAULT)
另外,還可以使用函數OCIStmtFetch來提取固定數目的記錄,其函數使用說明如下:
函數原型:sword OCIStmtFetch ( OCIStmt *stmtp,
OCIError *errhp,
ub4 nrows,
ub2 orientation,
ub4 mode )
參數說明:
*stmtp——需要執行的陳述句柄;
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
nrows——需要提取的記錄的條數;
orientation——該參數只有唯一一個缺省值:OCI_FETCH_NEXT;
mode——默認為OCI_DEFAULT;
該函數使用舉例如下:sword OCIStmtFetch (stmtp,
errhp,
rows_number,
OCI_FETCH_NEXT,
OCI_DEFAULT)
該函數成功執行,而無數據時,返回OCI_NO_DATA;
十一、事務提交。
在執行陳述句柄后,有的語句如insert、delete等需要提交當前事務,從而真正實現insert、delete等功能。OCI8使用函數OCITransCommit來實現這一功能。
函數原型:sword OCITransCommit ( OCISvcCtx *svchp,
OCIError *errhp,
ub4 flags )
參數說明:
*svchp——已分配并設置成功的服務句柄;其值等于于OCIStmtExecute函數的srchp參數值。
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
flags——提交標志。默認為0;
該函數使用舉例如下:OCITransCommit(svchp, errhp, (ub4) 0)
十二、事務回滾。
在執行完陳述語句后,若需要取消當前執行的操作,則需要回滾當前事務。OCI8使用函數OCITransRollback來完成該功能。
函數原型:sword OCITransRollback(dvoid *svchp,
OCIError *errhp,
ub4 flags )
參數說明:
*svchp——需要回滾當前事務的服務句柄;其值等于于OCIStmtExecute函數的srchp參數值。
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
flags——回滾標志。目前只有一個唯一的取值得:OCI_DEFAULT;
該函數使用舉例如下:OCITransRollback(svchp,
errhp,
OCI_DEFAULT)
十三、斷開與數據庫的連接
斷開與數據庫的連接需要進行下面一系列工作:結束當前會話、斷開與數據庫連接服務、釋放分配的各個句柄。下面分別說明各項工作所使用的oci函數。
結束當前會話:如果要斷開與數據庫的連接,則需要先結束當前會話,使用函數OCISessionEnd來完成該功能。執行成功,返回0
函數原型:sword OCISessionEnd(OCISvcCtx *svchp,
OCIError *errhp,
OCISession *authp,
ub4 mode)
參數說明:
*svchp——需要斷開的服務句柄;
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
*authp——會話句柄;
mode——會話結束模式。目前只有一種模式:OCI_DEFAULT;
該函數使用舉例如下:OCISessionEnd(svchp,
errhp,
authp,
(ub4) 0)
斷開與數據庫的連接服務:當前會話結束后,需要斷開與服務器的連接,結束用戶對數據庫的操作。OCI8使用函數OCIServerDetach來完成該任務。執行成功,返回0;
函數原型:sword OCIServerDetach(OCIServer *srvhp,
OCIError *errhp,
ub4 mode )
參數說明:
*svchp——需要斷開的服務器句柄;
*errhp——已分配成功的錯誤類型句柄;若該函數執行出錯,則該參數承載出錯的原因;
mode——執行模式,目前只有一種模式:OCI_DEFAULT;
該函數使用舉例如下:OCIServerDetach(srvhp,
errhp,
(ub4) OCI_DEFAULT)
釋放分配的各個句柄:在結束當前會話、斷開與數據庫的連接后,由于我們手動分配了很多句柄,系統不會自動釋放,因而需要手工釋放這些句柄,清掃使用環境。OCI8里,使用函數OCIHandleFree來釋放各個句柄。
函數原型:sword OCIHandleFree(dvoid *hndlp,ub4 type)
參數說明:
*hndlp——需要釋放的句柄;
type——該句柄的類型。參見OCIHandleAlloc函數說明的type參數;
注:使用OCIHandleAlloc函數分配了哪些句柄,那么就需要用該函數釋一一放這些句柄;
附錄:使用OCI8函數與數據庫交互大致步驟
一、定義并初始化所需各變量
envhp、srvhp、errhp、svchp、authp、hndlp、stmthp、等等
二、連接數據庫
1、 OCIInitialize。初始化OCI程序環境
2、 OCIEnvInit。 初始化OCI環境句柄
3、 OCIHandleAlloc。分配各句柄,需要分配的句柄類型如下:
OCI_HTYPE_SVCCTX,
OCI_HTYPE_ERROR,
OCI_HTYPE_SESSION,
OCI_HTYPE_SERVER,
4、 OCIServerAttach。指定資料源路徑
5、 OCIAttrSet。設置各項參數。需要設置的參數類型如下:
OCI_ATTR_SERVER 使用的句柄型為OOCI_HTYPE_SVCCTX
OCI_ATTR_USERNAME
OCI_ATTR_PASSWORD
上面兩個參數使用的句柄類型為OCI_HTYPE_SESSION
6、 OCISessionBegin。創建并開始會話
7、 OCIAttrSet。設置會話參數類型OCI_ATTR_SESSION,使用句柄為OCI_HTYPE_SVCCTX
8、 OCIHandleAlloc。分配OCI_HTYPE_STMT型陳述句柄
三、操作數據庫
1、OCIStmtPrepare。準備事件處理
2、OCIBindByPos、OCIBindByName(OCIDefineByPos)綁定(定義)變量。如果是多行資料,則需要使用
OCIBindArrayOfStruct(OCIDefineArrayOfStruct)函數來綁定(定義)存放該數據的數組
3、OCIStmtExecute。執行SQL語句
4、OCITransCommit(OCITransRollback)。提交(回滾)當前事務
四、斷開數據庫
1、OCISessionEnd。結束會話
2、OCIServerDetach。斷開與服務器的連接
3、OCIHandleFree。釋放已分配的各句柄。需要釋放的句柄如下:
OCI_HTYPE_SVCCTX,
OCI_HTYPE_ERROR,
OCI_HTYPE_SESSION,
OCI_HTYPE_SERVER,
OCI_HTYPE_STMT
OCI_HTYPE_ENV
五、提取出錯描述信息
1、OCIErrorGet。上述各函數若執行失敗,都可以使用該函數來提取出錯信息的ORCALE描述。