技術交流

Using ADODB with PHP and Oracle (Part I)

蘭江濤 蘭江濤

前面幾篇文章我們討論了Oracle和PHP5結合Apache Web Server開發環境的搭建及最近發佈的PHP5語言的一些新特徵。在本文中,我們將討論如何讓PHP連結到Oracle Database。

PHP 連結到Oracle主要有以下幾種方式:

  • Oracle擴展庫(Oracle Extension):為Oracle 早期版本(7.0 以前版本)所設計,現在已經廢棄不用了。
  • OCI8擴展庫:如其名稱一樣,是為Oracle8i以後的版本所設計,支持9i,10g,11g等版本。
  • PEAR DB Library:非常成熟的DB Layer Library。
  • ADODB Library:第三方Library,經過廣大PHPer的測試和眾多PHP Web Application的驗證,穩定強壯的ADODB現在已經發佈了4.5.2版本。它是一個使用十分廣泛的第三方 Library。本文將重點介紹此 Library。

PHP連結Oracle,首先要打開PHP設定檔中的對Oracle擴展的支持,重啟Apache Server之後,寫一個簡單的 PHP 程式,phpinfo()檢測Oracle Extension OCI8有沒有啟用。

Run 這個程式,在面頁上搜尋 oci8,如找得到說明 oracle extension啟用成功。 從http://adodb.sourceforge.net下載ADODB library,放到你的程式可以訪問到的Directory。 使用Oracle Extension連結Oracle 打開Oracle Extension之後,我們就可以用PHP built-in的OCI functions。


// 用Oracle預設的測試User scott/tiger連結到oracle database
 $tnsname = 'hcp';
 $conn = OCILogon('scott','tigger',$tnsname);
 $stmt = OCIParse($conn,'select * from emp where empno>:emp_no');
OCIBindByName($stmt,':emp_no',1200);
$r = OCIExecute($stmt);
While (OCIFetchInto($stmt,$result))
{
  Print_r($result);
  Echo '
'; }// end while loop // Line 1:指定這次連結的Oracle Database的tnsname叫做'hcp'。 // Line 2:用user 'scott',password 'tigger' 連結到'hcp',產生一個Connection Handler。 // Line 3:利用Connection Handler解析Select SQL Statement,其中傳了一個員工編碼 (emp_no)的變數。 // Line 4:給變數emp_no賦值。 // Line 5:執行查詢並把查詢的結果放到變數$r中。 // 用 ADODB 連結 Oracle   include_once '/path/to/adodb.inc.php';   $tnsname = 'hcp';   $Db = NewADODBConnection('oci8');    $Db->Connect($tnsname,'scott','tigger');   $result = $Db->Exeute('select * from emp where empno > :emp_nmo',              array('emp_no'=>1200));   while($row = $result->FetchRow()){    print_r($row);    echo '
';   }// end loop

忽略connection初始化部分代碼,兩段代碼十分相似。

ADODB 查詢 (Query)

如果您是從 Microsoft平臺轉換過來的程式撰寫人員,對Microsoft的Ado不會陌生。你也可以用標準的MS的方式,如 MoveNext()方法。


   $result = $Db->Execute('select * from emp
   where empno>:emp_no',array('emp_no'=>1200));
    While(!$result->EOF){
     Print_r($result->fields);
     $result->MoveNext();
    }// end loop

如果您想傳回2-D array的話,您可以使用 GetArray(),GetRow()或是GetAll()。


  $recordset = $Db->GetArray('select * from emp');
  Print_r($recordset);

  $recordset1 = $Db->GetAll('select * from emp');
  Print_r($recordset1);
  $row = $Db->GetRow('select * from emp where empno=1200'); // only one row selected
  Print_r($row);

如果只需要挑一個column,比如我們要得到資料count的筆數:


  $cnt = $Db->GetOne('select count(*) from emp');
  Echo $cnt;

分頁模式查詢 (Pagination Query)

Web Application在查詢到大量資料時,常常會用到分頁的功能。像MySQL等Database本身就提供了limit的功能。可是在Oracle中卻沒有此built-in功能供我們來使用。如果不用ADODB Library的話,自己也可以寫Nesting SQL來實現這個功能,不過非常麻煩,也容易出錯。值得慶幸的是,ADODB已經為我們準備好了同MySQL limit一樣功能的function供調用。您不用瞭解其內部複雜的運作原理,調用它就像 built-in的function一樣簡單。


// mysql sql
  $sql = 'select empno,ename from emp where deptno = 100 limit 3,5';
  $rs = $Db->GetArray($sql);
  
// Oracle SQL
$sql = 'select *
     from (select rownum as xrownum, empno, ename from emp)
     where xrownum > 3
     and xrownum <= 5';
  $rs = $Db->GetArray($sql);
 
// Using ADODB
  $offset = 3;
  $limitrows = 2;
  $rs = $Db->SelectLimit('select rownum as xrownum,empno,ename from emp',$limitrows,$offset);

查詢模式設定(Fetch Mode)

ADODB Library定義了三個常量 (constant),分別代表三種Fetch Mode。  ADODB_FETCH_NUM:傳回以數字為下標(index)的array,設定方法:    $Db->SetFetchMode(ADODB_FETCH_NUM);  ADODB_FETCH_ASSOC:傳回以欄位名稱為下標(index) 的array,設定方法:    $Db->SetFetchMode(ADODB_FETCH_ASSOC);   ◎注意:Oracle中是傳回大寫欄位名稱為下標(index)的 array。  ADODB_FETCH_BOTH: 同時傳回數位和文字為下標(index)的 array,設定方法:    $Db->SetFetchMode(ADODB_FETCH_BOTH);   ◎注意:除非有特殊的需要,不建議在大量資料時使用此Mode,會最影響 Performance。ADODB中 Oracle default fetch Mode就是ADODB_FETCH_BOTH,建議手動設定成欄位元名稱或數字為 index的Mode。