技術交流

Using ADODB with PHP and Oracle (Part II)

站在巨人的肩膀上

在 (Part I) 中我們討論了用傳統方式連結到 Oracle Database 的方法和使用 ADODB 連結 Oracle Database 的方式的不同,從 Oracle Database 中取資料的方法 ( GetArray、GetAll、GetRow、GetOne )及模仿 MySQL limit 功能的 SelectLimit()方法。在本文中,我們將討論 ADODB 連 Oracle Database時如何Call Oracle Store Procedure 和 Functions。

開始之前,我們先列出 Oracle Database 中用 PL/SQL 撰寫的 Procedure 及 Function. 假定 Database Connection Handler 為 $DBConn (在後面的 PHP 代碼中有用到此變數)。


// Procedure 只有 in 參數
Procedure my_proec (p_in_param in varchar2)
Is
Begin
   // do something here
End;

// Procedure 有 out 參數
Procedure my_proec (p_in_param in varchar2 ,p_out_param out varchar2)
Is
Begin
  P_out_param :='This is input data->'|| p_in_param ;
End;

// Function
Function my_func (p_in_param in varchar2 ,p_out_param out varchar2) return number
Is
Begin
  P_out_param :='This is input data->'|| p_in_param ;
  Return 1;
End;

Call Oracle Store Procedure

ADODB 的 Oracle Driver 中專門針對 Oracle Database的特性撰寫了 Call Procedure 的方法。

在 Procedure 中如果沒有 out 參數,可以採用如下兩種方法來執行:

Execute

//PHP Code
$stmt = 'begin my_proc(:p_in_param); end;';
 $DBConn->Execute($stmt,array('p_in_param'=>' 這是輸入的資料'));
// 下面是從 eHR系統中摘錄出的程式代碼片段
 $stmt = 'begin 
pk_erp.p_set_segment_no(:companyid);pk_department.p_set_base_date(sys
date);pk_erp.p_set_username(:user_seq_no);end;';
 $this->DBConn->Execute($stmt, 
            array('companyid'=> $this->companyID,
               'user_seq_no'=>$user_seqno));

當用 Execute 方式來執行 Procedure時,在所要執行的 Procedure 前後要加上 “ begin … end; ”如上面的代碼片段。 所有的 PL/SQL Statement 必須在一行(如從eHR系統中摘錄出來的程式版片段),請不要在代碼中回車(也就是說不能有 return code)。可以執行多個 procedure,中間用分號隔開。

Prepare /Bind Variables/Execute

//PHP Code
$stmt1 = 'begin my_proc(:p_in_param); end;';
  $stmt = $DBConn->PrepareSP ( $stmt1 ); 
  $ DBConn->InParameter ( $stmt, '這是輸入的資料', 'p_in_param', 20 ); 
  //$DBConn->Execute($stmt); 
  // 如果在 Procedure中執行了 insert,update,delete,需要 commit 的,要加上
  // StartTrans()和 CompleteTrans() 的方法, 如下:
  //$DBConn->StartTrans (); // begin transaction
  $DBConn->Execute($stmt );
  //$DBConn->CompleteTrans (); // end transaction

使用bind variable 的方式來傳參數,用 ADODB 的 InParameter ( $stmt、 $var、 $name、 $maxLen = 4000、 $type = false ) 或 OutParamete r ( $stmt、 $var、 $name、 $maxLen = 4000、 $type = false )方法,參數說明: $stmt:經過PrepareSP()處理過的 PL/SQL Statement

  • $var:參數的值
  • $name:參數名稱
  • $maxLen:數據長度,default 4000

在 Procedure 中如果有 out 參數時,必須使用上述方式的第二種。因為有輸出的值,所以在 PHP 代碼中必須 declare 一個變數來存放輸出的值。


// 摘錄自 her系統中的代碼片段
$_submit_result = array ("days" => "", "hours" => "", "msg" => "",
"is_success" => "" );
  $stmt1 = "begin begin pk_erp.p_set_segment_no(:in_company_id1);  
end; begin pk_erp.p_set_username(:in_user_seqno); end; begin wf.pkg_work_flow.p_submit_absence_apply(pi_seg_segment_no=>:in_compan
yid,pi_absence_flow_sz_id=>:in_workflow_seqno,po_days=>:out_days,po_h
ours=>:out_hours,po_errmsg=>:out_msg,po_success=>:out_issuccess); 
end;end;";
  $stmt = $this->DBConn->PrepareSP ( $stmt1 );
  $this->DBConn->InParameter ( $stmt, $companyid, 
"in_company_id1",10 );
  $this->DBConn->InParameter ( $stmt, $companyid,
"in_companyid", 10 );
  $this->DBConn->InParameter ( $stmt, $user_seqno,
"in_user_seqno", 10 );
  $this->DBConn->InParameter ( $stmt, $workflow_seqno,
"in_workflow_seqno", 10 );
  $this->DBConn->OutParameter ( $stmt, $_submit_result ["days"], 
"out_days", 5 );
  $this->DBConn->OutParameter ( $stmt, $_submit_result["hours"],
"out_hours", 6 );
$this->DBConn->OutParameter ( $stmt, $_submit_result ["msg"],
"out_msg", 2000 );
$this->DBConn->OutParameter ( $stmt, $_submit_result
["is_success"], "out_issuccess", 2 );
//$this->DBConn->debug = true;
$this->DBConn->StartTrans (); // begin transaction
$this->DBConn->Execute ( $stmt );
$this->DBConn->CompleteTrans (); // end transaction
return $_submit_result;

其它同上面的說明,值得一提的是,在代碼的開始 declare 了一個 array來存放多個 out 的變數(當你有多個out 參數時可以採用此方法,只有一個 out 參數,直接 declare一個變數賦初值就可以了)。

Call Oracle Store Function

Function 一定會有 return的值,所以跟 Procedure 的方式有所不同。

只有 In Parameter

當只有 In Parameter時問題就簡單的多了。因為有 function 有 return value,所以可利用標準的 SQL Select 來解決這個問題。


$sql = 'select my_func(:p_in_param) from dual';
 $outval = $DBConn->GetOne($sql,array('p_in_param'=>'some data'));
 Echo $outval;

當只有 In Parameter時,可以利用 Oracle Database 的 dual table,用 select 的方式來執行這個 function,然後用 ADODB 的 GetOne()來得到 function 執行的結果。

既有 In Parameter 也有 Out Parameter

限於篇幅,本期就介紹到此。既有 In Parameter 也有 Out Parameter 的方支將在下一期電子報中的 《Using ADODB with PHP and Oracle (Part III) 》 中介紹。

閱讀更多