Proc也就是嵌入式C,與informix的ESQ/C有相似之處,本部分主要列出Proc與Esql的區別,相同部分請參見informix部分。sql
1.數組功能數據庫
Proc中支持使用宿主變量數組一次查詢SELECT/插入INSERT多條記錄。在某些狀況下很是有用,但不具備移植性。數組
2.sqlca通信區結構oracle
struct sqlca { char sqlcaid[8]; long sqlabc; long sqlcode; struct { unsigned short sqlerrml; char sqlerrmc[70]; } sqlerrm; char sqlerrp[8]; long sqlerrd[6]; char sqlwarn[8]; char sqlext[8]; }; 函數
當MODE={ANSI13|ORACLE}時,要求說明SQLCA,不說明將致使編譯或鏈接錯誤。當MODE={ANSI|ANSI14}時,SQLCA的說明是可選的,但必須說明一個SQLCODE狀態變量。性能
說明形式:spa
EXEC SQL INCLUDE sqlca;
當Proc源程序由多個文件組成時,sqlca說明在一個文件裏,其餘文件使用以下引用方式:操作系統
#define SQLCA_STORAGE_CLASS extern
可經過定義符號SQLCA_INIT來初始化SQLCA。命令行
字段說明:指針
初始化爲sqlca,用於標示一個SQL通信區。
保存SQL通信區的長度,以字節爲單位。
最近執行的SQL語句的狀態。有如下值:
在Oracle中,「記錄沒有找到」的錯誤碼有兩個:在ANSI模式下是100,在Oracle模式下是1403。
保存sqlerrm.sqlerrmc中信息文本的長度。
保存與sqlcode相對應的錯誤信息文本,最長不超過70個字符。要得到超過70個字符的完整信息,須要使用sqlglm()函數。
sqlglm函數說明以下:
sqlglm( message_buff, &buffer_size, &message_length );
其中,message_buff是文本緩衝區;
buffer_size存放緩衝區的長度,以字節爲單位;
message_length是錯誤信息的實際長度。
ORACLE錯誤信息的最大長度是512字節。
保留,未使用。
sqlerrd[0]:保留;
sqlerrd[1]:保留;
sqlerrd[2]:保存當前sql語句處理的行數。當語句處理失敗時,該值無定義,當處理過程當中出錯時,則該值爲成功處理的記錄數;
sqlerrd[3]:保留;
sqlerrd[4]:保存相對位移,指出在哪一個字符位置開始出現(語法)分析錯誤。第一個字符的相對位移是0;
sqlerrd[5]:保留。
有8個元素,當有警告發生時,相應元素被設置位'W'。
sqlwarn[0]:若是其餘標誌被設置,則其也被設置。若其爲空,則表示其餘7個所有沒有設置;
sqlwarn[1]:若是字符數據輸出到宿主變量時被截斷,則設置該標誌,對於數字數據被截斷並不設置該標誌。爲了檢查具體的截斷狀況,可查看宿主變量對應的指示變量,指示變量的值是列的原始長度。
sqlwarn[2]:未使用;
sqlwarn[3]:若是查詢選擇的列數不等於宿主變量的個數,則設置該標誌;
sqlwarn[4]:若是DELETE和UPDATE語句沒有WHERE子句,則設置該標誌;
sqlwarn[5]:當執行CREATE語句因爲PL/SQL編譯錯誤失敗時,設置該標誌;
sqlwarn[6]:未使用;
sqlwarn[7]:未使用。
保留。
3.登陸數據庫
有以下三種形式:
形式1:
EXEC SQL CONNECT :username IDENTIFIED BY :password;
其中,username和password是CHAR或VARCHAR類型的宿主變量,分別包含用戶名和密碼。這裏必須使用宿主變量,不能直接使用字符串。
形式二:
EXEC SQL CONNECT :user_pwd;
其中宿主變量user_pwd包含由字符’/’分隔的用戶名和密碼,即(username/password)。
形式三(自動登陸):
char oracleid = ‘/’; EXEC SQL CONNECT :oracleid;
使用用戶名OPS$username登陸,其中username是當前登陸到操做系統上的用戶名或任務名。
[ EXEC SQL DECLARE db_link_name DATABASE; ] EXEC SQL CONNECT :username IDENTIFIED BY :password [ AT db_link_name ] USING :db_name;
其中,db_name包含遠程數據庫名(對於oracle8i,就是在配置文件tnsnames.ora中定義的名稱)。
能夠爲該鏈接定義一個鏈接名,db_link_name能夠是一個標示符,或者是宿主變量。若爲標示符,則須要使用DECLARE DATABAE進行說明。
若使用了AT子句,則在後面的SQL操做中也要指定該鏈接,不然操做的是缺省鏈接上的數據,而不是AT指定的鏈接。如:
EXEC SQL AT db_link_name SELECT…; EXEC SQL AT db_link_name INSERT…; EXEC SQL AT db_link_name UPDATE…; EXEC SQL AT db_link_name DECLARE cursor_name CURSOR…;
不能在PREPARE、DESCRIBE、OPEN、FETCH、CLOSE中使用AT子句。
可使用多條EXEC SQL CONNECT AT語句登陸到多個數據庫上,或爲同一個數據庫創建多個鏈接。
EXEC SQL CREATE DATABASE LINK link_name CONNECT TO username IDENTIFIED BY password USING db_name;
以後操做數據庫對象時要指定鏈名:
EXEC SQL SELECT * FROM emp@link_name;
Oracle中不支持滾動遊標。
Oracle中沒有BEGIN WORK之類的事務開始語句,程序中的第一個SQL語句(非CONNECT語句)自動開始一個事務。
事務的結束有以下狀況:
EXEC SQL [ AT :link_name ] COMMIT WORK [ RELEASE ];
完成以下功能:
使用RELEASE除了完成上述功能外,還釋放全部資源並切斷與ORACLE的鏈接。
程序中必須用COMMIT/ROLLBACK RELEASE來顯示結束最後一個事務並斷開鏈接。
事務保留點是事務內的標誌點,創建方法以下:
EXEC SQL [ AT link_name ] SAVEPOINT savepoint_name;
保留點用於部分回滾。
若是給兩個保留點設置相同的名字,則前一個保留點被取消。每一個用戶會話期的活動保留點最大數爲5(缺省值)。該值可修改配置文件init.ora中的SAVEPOINTS來改變,最大255。
事務級回滾:
EXEC SQL [ AT link_name ] ROLLBACK WORK [ RELEASE ];
完成以下功能:
部分事務回滾:
EXEC SQL [ AT link_name ] ROLLBACK WORK TO \ SAVEPOINT savepoint_name;
完成以下功能:
若是執行一條SQL語句失敗,ORACLE會自動將其回滾,並在sqlca.sqlcode中返回一個錯誤碼。
結構構成:
struct SQLDA { int N; char **V; int *L; short *T; short **I; int F; char **S; short *M; short *C; char **X; short *Y; short *Z; };
指定要描述的選擇表項或虛擬輸入宿主變量的最大個數。N肯定了描述區中數組的元素個數。在發出DESCRIBE命令以前,必須用庫函數sqlald()把N設置爲描述區中數組的維數。在DESCRIBE以後,必須再把N設置爲所描述的選擇表項或虛擬輸入宿主變量的實際個數,該數據被存儲在F變量中。
V是一個數組指針,其元素分別指向緩衝區中存儲的每個選擇表項或實輸入宿主變量值。
當對該描述區進行分配時,函數sqlald()把數組元素V[0]~V[N-1]設置爲0。
對於選擇描述區,必須在發FETCH命令以前分配數據緩衝區和設置該數組。
對於結合緩衝區,必須在發OPEN命令以前設置該數組。
L是一個指針,它指向一個數組,該數組包含存儲在數據緩衝區中的選擇表項或實輸入宿主變量的長度。
對於選擇描述區,DESCRIBE SELECT LIST語句把長度數組設置爲每個選擇表項所指望的最大數。
在FETCH以前必須把L[i]從新設置爲所須要的數據緩衝區的長度。
對於結合緩衝區,在發OPEN命令以前,必須設置長度數組。
T是一個指針,它指向一個數組,該數組存放選擇表項或實輸入宿主變量的數據類型代碼。
對於選擇描述區,DESCRIBE SELECT LIST語句把數據類型代碼數組設置爲選擇表項的內部數據類型(如CHAR、NUMBER或DATE)。
由於ORACLE數據類型的內部格式很難處理,因此在FETCH以前,能夠設置某些數據類型。
T[i]的高位指出第i個選擇表項的NULL/NOT NULL狀態。在發OPEN或FETCH以前,必定要清除該位。用庫函數sqlnull()來檢索數據類型代碼和清除NULL/NOT NULL位。
對於結合描述區,DESCRIBE BIND VARIABLES把數據類型代碼的數組設置爲0。在發OPEN以前,必須從新設置存儲在每個元素的數據類型代碼。該代碼表示V[i]所指向的數據緩衝區的外部(C)數據類型。
I是一個數組指針,其元素分別指向數據緩衝區中每個指示器變量的值。必須設置元素I[0]~I[N-1]。
對於選擇緩衝區,必須在發FETCH以前設置該地址數組。當ORACLE執行FETCH以後,若是第i個返回的選擇表項值爲NULL,那麼I[i]所指向的那個指示器變量的值被置爲-1,不然,它被置爲0或一個正整數(值被截短)。
對於結合描述區,必須在發OPEN以前設置地址數組和相關的數據緩衝區。當ORACLE執行OPEN時,I[i]所指向的那個指示器變量的值決定第i個實輸入宿主變量是不是一個NULL值。若是指示器變量的值爲-1,則其相關實輸入宿主變量的值爲NULL。
F是DESCRIBE所發現的選擇表項或虛擬輸入宿主變量的實際個數。所以,F是由DESCRIBE來設置。若是F<0,則表示DESCRIBE發現了過多的選擇表項或虛擬輸入宿主變量(相對於N變量),F的絕對值就是實際個數。
S是一個數組指針,其元素分別指向數據緩衝區中所存儲的每個選擇表項或虛擬輸入宿主變量的名字。
使用sqlald()來分配該數據緩衝區,並把其地址存放在S數組中。
M是一個指針,它指向一個數組,該數組存放緩衝區中所包含的選擇表項或虛擬輸入宿主變量名字最大長度。這些緩衝區由S數組元素尋址。
當分配一個描述區時,sqlald()設置該數組元素M[0]~M[N-1]。當對S[i]指向的數據緩衝區存儲時,第i個名字被截成M[i]中的長度(若是有必要的話)。
C指向一個數組,該數組元素包含選擇表項或虛擬輸入宿主變量名字的當前長度。
DESCRIBE設置C[0]~C[N-1]。
X是一個數組指針,其元素分別指向數據緩衝區中所存儲的每個指示器變量的名字。只能把指示器變量的名字與實輸入宿主變量聯繫起來,所以,X只適用於結合緩衝區。
用sqlald()來分配數據緩衝區並把它們的地址存儲在X數組中。
DESCRIBE BIND VARIABLES指示ORALCE把第i個指示器變量的名字存儲在X[i]所指向的數據緩衝區中。
Y指向一個數組,該數組的元素分別包含每個指示器變量名字的最大長度。Y也只適用於結合緩衝區。
Z指向一個數組,該數組的元素分別包含當前每個指示器變量名字的最大長度。Z也只適用於結合緩衝區。
EXEC SQL INCLUDE sqlda; sqlda *bind_dp; bind_dp = sqlald( … );
sqlald函數爲sqlda結構分配空間。函數格式以下:
descriptor_name = sqlald(max_vars, max_name, max_ind_name );
其中:
max_vars:sqlda結構中要描述的選擇表項或虛擬輸入宿主變量的最大個數;
max_name:選擇表項或虛擬輸入宿主變量名字的最大長度;
max_ind_name:指示器變量名的最大長度。對於選擇sqlda,該項設置爲0。
通常用指針來引用sqlda。
對於選擇描述區,DESCRIBE SELECT LIST返回ORACLE的內部數據類型。一般,該內部數據類型正好對應所要用的外部數據類型;可是,個別的映射難以處理,所以,能夠從新設置T變量的某些元素。ORACLE在FETCH時作必要的內部和外部數據類型的轉換。
對於結合緩衝區,DESCRIBE BIND VARIABLES並不返回實輸入宿主變量的數據類型,而只返回它們的個數和名字。因而,必須顯示設置數組T,以告訴ORACLE每個實輸入宿主變量的外部數據類型。ORACLE在OPEN時作外部和內部數據類型之間的必要轉換。
除了設置T變量外,有些狀況下,還要設置緩衝區長度。在FETCH以前必須從新設置L變量的相應元素,以告訴ORACLE所用的緩衝區長度。
庫函數sqlprc()分離精度和定標。一般在DESCRIBE SELECT LIST以後使用它,而且它的第一個參數時L[i]:
sqlprc( long *length, int *precision, int *scale );
其中,length存儲一個ORACLE NUMBER值得長度。長度存放在L[i],該值得定標和精度存放在相應的低字節和下一個高字節中;
precision存放NUMBER值精度。精度是有效位數,若是選擇表項引用的是未指定大小的NUMBER值,則它被設置爲0。在這種狀況下,可假定爲最大精度;
scale存放NUMBER值定標。定標指出在什麼地方舍入。如,2:3.456 -> 3.46;-3:3456 -> 3000。
對於每個選擇表列(不是表達式),DESCRIBE SELECT LIST在T變量中返回一個Null/Not Null指示。若是第i個選擇表項被強制爲Not Null,那麼T[i]的高位被清除,不然被設置。
在OPEN或FETCH以前,若是Null位被設置的話,則必須清除它。使用庫函數sqlnul來發現一個列是否容許Null,並清除該數據類型的Null狀態位:
sqlnul(unsigned short *value_type, unsigned short *type_code, \ int *null_status );
其中,value_type存放一個選擇表項的數據類型代碼,即T[i];
type_code返回該選擇表列的數據類型代碼,其高位被清除;
null_status返回選擇表列的Null狀態。1表示容許Null;0表示不容許Null。
在說明段說明一個串型的宿主變量,以保存查詢語句的文本。
EXEC SQL BEGIN DECLARE SECTION VARCHAR select_stmt[120]; EXEC SQL END DECLARE SECTION
說明選擇和結合SQLDA。
EXEC SQL INCLUDE sqlda; sqlda *select_des; sqlda *bind_des;
分配選擇和結合緩衝區的空間。
使用sqlald()函數分配,若是max_name非0,則分配由指針變量S、M和C尋址的數組。若是max_ind_name不是0,則分配由指針變量X、Y和Z尋址的數組。若是max_name和max_ind_name爲0,則不分配相應的空間。
若是sqlald()成功,則返回該描述區的地址,失敗則返回空指針。
select_des = sqlald(3, 5, 0); bind_des = sqlald(3, 5, 4);
對於選擇描述區,老是把max_ind_name設置爲0。
設置能被DESCRIBE的選擇表項和虛擬輸入宿主變量的最大個數。
select_des->N = 3; bind_des->N = 3;
把查詢語句文本存放在串型宿主變量中。
strcpy(select_stmt.arr, 「select … where …」 ); select_stmt.len = strlen(select_stmt.arr);
PREPARE宿主串中的查詢語句。
EXEC SQL PREPARE sql_stmt FROM :select_stmt;
DECLARE一個查詢光標。
EXEC SQL DEACLARE emp_cursor CURSOR FOR sql_stmt;
注意:對於此種方法的動態sql語句(不僅是查詢語句),都必須說明一個光標,在非查詢語句狀況下,打開光標即執行該動態sql語句。
把實輸入宿主變量DESCRIBE進結合描述區中。
EXEC SQL DESCRIBE BIND VARIABLES FOR sql_stmt INTO bind_des;
注意:在bind_des以前必定不加冒號。
把虛擬輸入宿主變量的個數從新設置爲DESCRIBE實際發現的個數。
bind_des->N = bind_des->F;
爲DESCRIBE發現的實輸入宿主變量取值和分配存儲空間。
如:
bind_des->L[i] = strlen( hostval ); bind_des->V[i] = malloc(bind_des->L[i] + 1); bind_des->I[i] = (unsigned short *)malloc(sizeof(short)); strcpy(bind_des->V[i], hostval); bind_des->I[i] = 0; bind_des->T[i] = 1;
用OPEN…USING打開與結合描述區相對應的光標。
EXEC SQL OPEN emp_cursor USING DESCRIPTOR bind_des;
注意:在bind_des以前必定不加冒號。
用DESCRIBE SELECT LIST語句描述選擇描述區。
EXEC SQL DESCRIBE SELECT LIST FOR sql_stmt INTO select_des;
注意:DESCRIBE把F設置爲該查詢選擇表項的實際個數,若是語句不是查詢,則被設置爲0。
此時NUMBER的長度仍然不能用,還須要用sqlprc()來分離精度和定標。
把選擇表項的個數從新設置爲DESCRIBE實際發現的個數。
select_stmt->N = select_stmt->F;
從新設置選擇表項的長度和數據類型,以便顯示它們。
如:
sqlnul(&(select_stmt->T[i]), &(select_stmt->T[i]), &nullok); switch( select_stmt->T[i]) { case 1: break; case 2: sqlprc(&select_stmt->L[i], &prec, &scal); if ( prec == 0 ) prec = 40; select_des->L[i] = prec + 2; if (scal < 0) select_des->L[i] += -scal; break; case 8: select_des->L[i] = 240; break; case 11:select_des->L[i] = 18; break; case 12: select_des->L[i] = 9; break; case 23: break; case 24: select_des->L[i] = 240; break; } select_stmt->V[i] = malloc(select_stmt->L[i]); select_stmt->I[i] = (unsigned short *)malloc(sizeof(short)); if (select_stmt->T[i] != 24) select_stmt->T[i] = 1;
用FETCH把提取的行放入選擇描述區所指向的數據緩衝區。
EXEC SQL FETCH emp_cursor USING DESCRIPTOR select_des;
在輸出緩衝區中,對於數據類型1,ORACLE使用存放在L數組中的長度,左對齊CHAR和VARCHAR2數據,右對齊NUMBER數據。
處理FETCH所返回的選擇表項。
釋放選擇表項、虛擬輸入宿主變量、指示器變量和描述區所用的空間。
使用free釋放malloc分配的空間。
使用sqlclu()庫函數撤銷描述區自己的存儲空間。
sqlclu(select_des); sqlclu(bind_des);
關閉光標。
EXEC SQL CLOSE emp_cursor;
在一個鏈接中,若該鏈接引用記數爲1,則關閉該鏈接也釋放遊標;如在同一個進程中打開鏈接,操做數據,關閉鏈接。
若鏈接記數大於1,如父進程打開鏈接,子進程共享該鏈接進行操做,則鏈接記數大於1,子進程不能作關閉鏈接操做。此時要釋放一個遊標,在關閉遊標後,還必須作commit或rollback;此外,還要設置release_cursor選項爲yes,設置方法是在proc命令行中增長release_cursor=yes,或在程序中編寫:
EXEC ORACLE OPTION(RELEASE_CURSOR=YES);
不然不能釋放,最終會報-1000錯:maximum open cursors exceeded。
Pro*C的命令格式以下:
proc INAME=filename [Option_name1=value1 Option_name2=value2 … ]
注意:等號兩側不能有空格。
在程序中指定選項的格式以下:
EXEC SQL OPTION(option_name=value);
編譯選項以下:
ASACC=YES|NO;
缺省值爲NO。指出清單文件是否爲了回車控制而遵循使用每一行第一列的ASA約定。
注意:只能在命令行上輸入。
CODE=ANSI_C|KR_C
缺省值爲KR_C。產生的C函數原型的格式。
DBMS=NATIVE|V6|V7
缺省值爲NATIVE。指定所用的ORACLE數據庫管理系統的版本,是6版、7版或本國版。
注意:只能在命令行上輸入。
用於定義一個符號,用於進行條件編譯。
若是在程序中輸入時,使用以下語法:
EXEC ORACLE DEFINE symbol;
ERRORS=YES|NO;
缺省值爲YES。指出預編譯程序的錯誤信息是否被髮送到終端和清單文件上,或僅僅給清單文件。
FIPS=YES|NO;
缺省值爲NO。當FIPS=YES時,若是使用一個ANSI SQL的ORACLE擴展,或以不一致的方式使用一個ANSI SQL性能,就發出警告(不是錯誤)信息。
HOLD_CURSOR=YES|NO;
缺省值爲NO。
當執行SQL數據操縱語句時,其相關的光標被連到光標高速緩衝存儲器中的一項上,該項又被依次鏈接到ORACLE專用的SQL區域上,該區域存儲處理該語句所需的信息。
當HOLD_CURSOR=NO時,在ORACLE執行完SQL語句或關閉光標後,預編譯程序直接撤去該鏈,釋放分析塊和分配給專用SQL區域的內存,並把該鏈標爲可再使用。這時另外一個SQL語句就又可以使用該鏈來指向光標高速緩衝存儲器的項了。
當HOLD_CURSOR=YES時,該鏈被保留,預編譯程序再也不使用它。這對常用的SQL語句是有用的。
注意:RELEASE_CURSOR=YES優先於HOLD_CURSOR=YES;HOLD_CURSOR=NO優先於RELEASE_CURSOR=NO。
HOST=C|COB74|COBOL|FORTRAN|PASCAL|PLI;
指出輸入文件的宿主語言。
INCLUDE=path;
缺省值爲當前目錄。指定EXEX SQL INCLUDE文件的目錄路徑,它只適用於使用目錄的操做系統。
IRECLEN=length;
缺省值爲80。指定輸入文件的紀錄長度。
注意:只能在命令行輸入,指定的值不該超過ORECLEN的值。
LINES=YES|NO;
缺省值爲NO。當LINES=YES時,預編譯程序對輸出文件加C預編譯程序命令#line。爲NO時不輸出。
LNAME=path and filename;
缺省值爲「輸入文件.LIS」。爲清單文件指定非缺省名。
注意:只能在命令行輸入。
LRECLEN=integer;
缺省值爲132。指定清單文件的記錄長度。
注意:只能在命令行輸入。
LTYPE=LONG|SHORT|NONE;
缺省值爲LONG。
指定清單類型。當LTYPE=LONG時,清單文件中包含輸入行;當LTYPE=SHORT時,不包含輸入行;當LTYPE=NONE時,不創建清單文件。
MAXLITERAL=integer;
缺省值爲1000(C語言)。指出預編譯程序生成的串文字的最大長度。
MAXOPENCURSORS=integer;
缺省值爲10。指定同時打開的光標數。每一個用戶處理能打開的光標的最大數由ORACLE初始化參數OPEN_CURSORS設置,其範圍爲5至255。該選項可指定一個較初始值小的值,必須比初始值至少低6。
MODE=ANSI|ISO|ANSI14|ISO14|ANSI13|ISO13|ORACLE;
缺省值爲ORACLE。指定程序遵循的標準。
ONAME=path and filename;
指定輸出文件名。
注意:只能在命令行上輸入。
ORACA=YES|NO;
缺省值爲NO。指出程序可否使用ORACLE通信區。
ORECLEN=integer;
缺省值爲80。指定輸出文件的記錄長度。
注意:只能在命令行輸入,值應大於等於IRECLEN的值。
PAGELEN=integer;
缺省值爲66。指定清單文件的每一物理頁的行數。
注意:只能在命令行上輸入。
RELEASE_CURSOR=YES|NO;
缺省值爲NO。
該選項用來控制光標和光標高速緩衝存儲器之間的鏈。爲了保證在關閉光標時使有關的資源被釋放,必須指定:
RELEASE_CURSOR=YES。
相關描述見HOLD_CURSOR。
SELECT_ERROR=YES|NO。
缺省值爲YES。
當SELECT_ERROR=YES時,若單行SELECT語句返回多於一行,或多行SELECT語句返回的行數比宿主數組能容納的還要多,則產生錯誤,且查詢的結果是不肯定的。當指定SELECT_ERROR=NO時,則不產生錯誤。
SQLCHECK=SEMANTICS|FULL|SYNTAX|LIMITED|NONE;
缺省值爲SYNTAX。指定語法和語義檢查的類型和範圍。
USERID=username/password;
指定ORACLE用戶名和密碼。
注意:只能在命令行上輸入。
XREF=YES|NO;
缺省值爲YES。指出是否在清單文件中列交叉索引表。