天天看點

OTL調用存儲過程/函數及注意事項

OTL 是 Oracle, Odbcand DB2-CLI Template Library 的縮寫,是一個C++編譯中操控關系資料庫的模闆庫,它目前幾乎支援所有的目前各種主流資料庫。OTL使用起來比較友善,其官方網站也提供了詳細的文檔和例子(http://otl.sourceforge.net/otl3.htmhttp://otl.sourceforge.net/otl3_examples.htm)。

最近在項目中需要使用OTL調用Oracle存儲過程,并且需要傳回遊标,在網上查了一下,相關的中文資料比較少,經過一番辛苦的查找和摸索,最後終于如願達到目的。在這裡把相關的經驗分享給大家,如有不對的地方,歡迎拍磚。

OTL調用Oracle存儲過程,其官方文檔中給出了相應的例子,位址是http://otl.sourceforge.net/otl4_ex149.htm。現節選關鍵部分如下:

otl_streami(1,

              "begin "

              "my_pkg.my_proc(:f1<int,in>,:f2<int,in>, "

              "         :str1<char[100],out>, "

              "         :cur1<refcur,out[50]>, "

              "         :cur2<refcur,out[50]>); "

              "end;",

              db // connect object

             );

  i.set_commit(0); // set stream"auto-commit" to OFF.

 char str1[101];

 float f1;

 char f2[31];

 otl_refcur_stream s1, s2; // reference cursorstreams for reading rows.

 i<<8<<4;

 i>>str1;

 i>>s1;

 i>>s2;

 cout<<"STR1="<<str1<<endl;

 cout<<"=====> Reading :cur1..."<<endl;

 while(!s1.eof()){ // while not end-of-data

  s1>>f1>>f2;

 cout<<"f1="<<f1<<", f2="<<f2<<endl;

 }

 cout<<"=====> Reading :cur2..."<<endl;

 while(!s2.eof()){ // while not end-of-data

  s2>>f1>>f2;

 cout<<"f1="<<f1<<",f2="<<f2<<endl;

 }

 s1.close(); // closing the reference cursor

 s2.close(); // closing the reference cursor

可以看出,調用存儲過程和執行普通的sql大同小異,也是通過otl_stream對象綁定相關參數,不同之處有以下幾點:

1.調用存儲過程/函數時,緩沖大小必須設定為1。

2.Sql聲明時語句必須采用”begin ……end;”的形式。存儲過程如果位于包内,還必須帶上包名。綁定參數除了聲明類型、大小以外,還必須指明參數的輸入輸出标志。傳回遊标的大小代表了遊标内的記錄數。

3.傳回遊标綁定的資料類型是otl_refcur_stream,就像普通的otl_stream一樣,可以使用while循環讀取其中的資料。遊标對象使用完畢後,别忘了使用close方法将其關閉。

在這個過程中,有兩個需要注意的地方:

1.OTL在輸入輸出參數的方向标志方面稍微有點不人性化,即要求所有的in、out與前面的逗号“,”之間不允許有空格、制表符等空白字元,否則就會無法識别方向标志而發生ORA-01008錯誤,并提示“并非所有變量都已綁定”。

       2.如果存儲過程記憶體在多條執行路徑,并且某些執行路徑并不傳回遊标的情況下,就需要程式員自己判斷在目前情況下是否需要接收遊标。如果目前存儲過程并未傳回遊标,而在c++程式中執行了提取(>>)操作,就會發生ORA-24338錯誤,并提示“未執行語句句柄”。此時,如果允許的話可以通過存儲過程傳回的其他變量判斷是否需要進行接收操作,如:

if(“00” == ret_code)      // 其中ret_code是存接收了儲過程執行狀态的變量

{

    o >> first_cur;

    o >> detail_cur;

}

OTL調用存儲函數和存儲過程基本相似,隻不過是多了一個傳回值而以。格式大緻如下:

otl_streami(1,

"begin "

"  :rc<int,out> :=my_pkg. my_func(:f1<int,in>,:f2<int,in>,"

            "        :str1<char[100],out>, "

            "         :cur1<refcur,out[50]>, "

"        :cur2<refcur,out[50]> "

"                          );  "

" end; ",

db // connect object

);

intres = 0;

charstr1[101];

floatf1;

charf2[31];

otl_refcur_streams1, s2; // reference cursor streams for reading rows.

 i<<8<<4;

i >> res;

 i>>str1;

 i>>s1;

 i>>s2;

這裡也有兩個需要注意的地方,一是sql聲明時存儲函數名前面的等号要用“:=”;再就是接收輸出時,首先接收函數傳回值,再依次接收其他輸出。其他操作同存儲過程一緻。關于調用存儲過程/函數時,sql聲明的具體格式,OTL提供了一個專門的函數create_stored_proc_call,可以生成相應的綁定sql。其具體使用方法參見http://otl.sourceforge.net/otl4_ex153.htm。

補充一下:筆者的環境是otl v4.0.218 OraClient11g vs2008sp1 winxp sp3。

支援部落客,請點選這裡,協助新站收錄,聊城市人和精工軸承有限公司 十分感謝!