程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle數據庫基礎 >> 特別版和Zend Core for Oracle

特別版和Zend Core for Oracle

編輯:Oracle數據庫基礎

安裝 Oracle 數據庫特別版和 Zend Core for Oracle

本部分介紹了如何安裝:

Oracle 數據庫特別版

Zend Core for Oracle

我們已經在下列系統上對安裝和配置進行了測試:

512MB 內存

5GB 硬盤空間

Red Hat Enterprise Linux (RHEL) 3

RHEL 4

Novell SUSE Linux Enterprise Server (SLES) 9

Oracle 數據庫特別版

Oracle 數據庫特別版是一款小型入門級數據庫,可以免費下載、開發和部署,並且可以自由地與應用程序一起分發,不需要支付數據庫許可費!

Oracle 數據庫特別版是使用與 Oracle 數據庫 10g 第 2 版產品(標准版和企業版)相同的基本代碼構建的,可以在 32 位 Windows 平台和 Linux 平台上使用。

Oracle 數據庫特別版比較適用於:

致力於 PHP、Java、.Net 以及其他需要數據庫的應用程序的開發人員

需要免費入門級數據庫來進行培訓和部署的 DBA

需要在其應用程序或產品中嵌入 Oracle 數據庫的獨立軟件供應商 (ISV)

需要免費的入門級數據庫的教育機構和學生

Oracle 數據庫特別版包含下列編程接口:

SQL、PL/SQL

Java、C 和 PHP

Windows .Net

Oracle Application Express

C++、ODBC、OLE DB

Oracle 數據庫特別版具有下列限制:

用戶數據最大為 4GB

單數據庫實例

使用一個 CPU

使用 1GB 內存

Oracle 數據庫特別版提供了基於浏覽器的管理界面,即 Oracle Application Express。

同行和產品專家通過 OTN 論壇提供支持。

安裝 Oracle 數據庫特別版

如果您的 libaio 版本不高於 0.3.96,則在安裝 Oracle 數據庫特別版之前必須安裝該庫。

Oracle Database Developer CD for Linux x86 上的安裝過程與下面的過程略有不同。如果從此 CD 進行安裝,請按照文檔 Start_Here.Html(位於此 CD 的根目錄下)中的說明執行操作。

要安裝 Oracle 數據庫特別版,執行下列操作:

以 root 用戶身份登錄或執行 su 命令

su

PassWord:

將 Oracle-xe-10.2.0.1-1.0.i386.rpm 復制到 /tmp,然後將目錄更改為 /tmp。

cp Oracle-xe-10.2.0.1-1.0.i386.rpm /tmp

cd /tmp

安裝 RPM

rpm -ivh Oracle-xe-10.2.0.1-1.0.i386.rpm

安裝了 Oracle 數據庫特別版。

配置數據庫。

/etc/init.d/Oracle-xe configure

對 Application Express 使用默認端口 8080,並對數據庫監聽器使用 1521。

輸入並確認默認用戶的密碼。

輸入 Y 或 N,指定是否希望數據庫在系統重新啟動時自動啟動。至此,已經配置並啟動了數據庫和數據庫監聽器。

測試 Oracle 數據庫特別版安裝

要測試 Oracle 數據庫特別版安裝,執行下列操作:

打開 web 浏覽器並輸入:

http://127.0.0.1:8080/apex

以用戶 system 的身份使用安裝過程中輸入的密碼登錄。

您應登錄了 Oracle。

Zend Core for Oracle

2005 年,Oracle 與 Zend TechnologIEs 已經開始合作開發了一個集成的解決方案,旨在幫助開發人員基於常用的 PHP 腳本語言創建並部署數據庫驅動的 Web 應用程序。

2005 年 10 月,Oracle 與 Zend 宣布了 Zend Core for Oracle (ZCO) 的通用版本。ZCO 提供了一個經過充分測試和完全受支持的 PHP 5 發行版本,其中包含與 Oracle 數據庫 10g 客戶端庫的集成,並使開發人員能夠在幾分鐘內啟動並運行 PHP 和 Oracle。

ZCO 是為 PHP 開發人員提供的一個預建產品系列,它使開發人員能夠更容易地在一個強健、可伸縮且可靠的基礎架構中開發和部署應用程序。該產品包括與 Oracle 數據庫客戶端庫的緊密集成,以及對 XML 和 Web 服務的原生支持,同時還支持應用日益廣泛的面向服務體系結構 (SOA)。它為數據庫驅動的應用程序提供了一個快速開發和部署的基礎。

Oracle 還在 Oracle 技術網上推出了 PHP 開發人員中心,致力於與 Oracle 相關的 PHP 開發。

Oracle 與 Zend 之間的協作加強了 Oracle 對開放源代碼 PHP 社區的貢獻。Oracle 新引入並優化的用於 PHP 的 OCI-8 擴展將交回 PHP 社區並集成到 ZCO 中。

這一協作通過幫助開發人員更有效地創建並部署數據庫驅動的應用程序,擴展了 Oracle 在開發源代碼上的投入。

Zend 支持 ZCO 和 PHP。

安裝 Zend Core for Oracle

要安裝 ZCO,執行下列操作:

以 root 用戶身份登錄或執行 su 命令(如果您尚未執行該操作)。

su

PassWord:

將 ZendCoreForOracle-v1.3.1-Linux-x86.tar.gz 復制到 /tmp,然後將目錄更改為 /tmp。

cp ZendCoreForOracle-v1.3.1-Linux-x86.tar.gz /tmp

cd /tmp

解壓縮已下載的 Zend Core for Oracle 軟件:

tar -zxf ZendCoreForOracle-v1.3.1-Linux-x86.tar.gz

文件解壓縮到一個名為 ZendCoreForOracle-v1.3.1-Linux-x86 的子目錄。

將目錄更改為 ZendCoreForOracle-v1.3.1-Linux-x8,然後啟動 Zend Core for Oracle 安裝:

cd ZendCoreForOracle-v1.3.1-Linux-x86

./install

在最初的 Zend Core for Oracle Installation 頁面中,單擊 OK。

在 Zend Core for Oracle V.1 頁面中,單擊 Exit。

當系統提示您接受許可條款時,單擊 Yes。

如果已經安裝了 PHP,則系統提示您備份並覆蓋現有的 PHP.ini 文件。單擊 Yes。

當系統提示您指定 Zend Core for Oracle 的安裝位置時,接受默認位置(或輸入您想要的位置),然後單擊 OK。安裝程序開始解壓縮安裝所需的文件。

當進度窗口指示已安裝所有軟件時,系統將提示您“Please enter the GUI password”。在 PassWord 域中,輸入要在訪問 Zend Core Console 時使用的密碼,然後單擊 OK。

當系統提示您“Verify the passWord”時,輸入上一步中指定的密碼,然後單擊 OK。

在 Zend Core 支持頁面中,您可以有選擇地輸入 Zend 網絡用戶 ID 和密碼,以便能夠使用 Zend Core Console 跟蹤對 Zend Core 和 PHP 組件的更新何時可用。如果您尚未注冊,或不希望跟蹤更新,則單擊 No。

下一頁提示您為 Zend Core 安裝選擇 Web 服務器。選擇與 Linux 一起安裝的默認的 apache。單擊 OK。

在確認 Web 服務器選擇頁面中,在“Do you wish to proceed?”的提示下,單擊 Yes。

在下一個安裝頁面中,系統將提示您“Please select an installation method for Apache 2.0.52”。選擇 apache 模塊作為方法,然後單擊 OK。

在下一個安裝頁面中,當系統提示您“Please select a virtual server for the Zend Core GUI”時,選擇 Main Server,然後單擊 OK。

在下一個安裝頁面中,在“Would you like to restart the Web Server”提示下,單擊 Yes。

在下一個安裝頁面中,將顯示一個指示 apachectl 腳本已更新的通知。單擊 OK。

下一個安裝頁面(包含“Thank you for installing Zend Core for Oracle”)列出了有用的配置命令和一個 Zend Core 引擎管理網頁。記下此信息,然後單擊 Exit。

將顯示一個最後確認頁面。單擊 OK 完成安裝。

Zend Core for Oracle 安裝現已完成。

配置 Zend Core for Oracle

在該部分中,您將配置控制網頁中默認錯誤報告的環境變量和 Zend Core 指令。

在 Web 浏覽器中輸入以下 URL,訪問 Zend Core Administration 頁面: http://127.0.0.1/ZendCore

輸入您在 Zend Core for Oracle 安裝過程中提供的 GUI 密碼。單擊 login >>> 圖標。

單擊 Configuration 選項卡顯示配置選項。

單擊 + 圖標展開 Error Handling 和 Logging 配置條目。

將 display_errors 指令設置為 On,以便開發過程中在 Html 腳本輸出中顯示錯誤。

由於有未保存的更改,因此頁面標題下將顯示“Unsaved configuration”消息。單擊 Save Settings 保存配置更改。

由於您已經進行了配置更改,因此必須重新啟動 Apache Web 服務器。在頁面標題下,注意提示您執行該操作的“Please Restart Apache”消息。單擊 Restart Server 重新啟動 apache 服務器。

單擊 Logout 退出 Zend Core for Oracle Administration 頁面。

測試 Zend Core for Oracle 安裝

要測試 ZCO 安裝,執行下列操作:

將有關創建虛擬目錄的信息添加到用戶的 home 目錄中。

創建一個公共虛擬目錄 public_Html。編輯 apache_HOME/conf/httpd.conf,刪除以下行中的“#”:

#UserDir public_Html

以普通用戶(非 root 用戶)的身份在 home 目錄中創建一個名為 public_Html 的目錄,將目錄更改為這個新創建的目錄,在命令窗口中輸入下列命令:

cd $HOME

mkdir public_Html

cd public_Html

創建一個名為 hello.php 的文件,在其中添加以下 PHP 代碼:

echo "Hello world!";

?>

打開 Web 浏覽器,輸入以下 URL:

http://127.0.0.1/'/hello.PHP

浏覽器中將顯示行“Hello world!”。

PHP OCI8 擴展

PHP oci8 擴展提供了用於訪問 Oracle 數據庫的 PHP 函數。Zend 和 Oracle 最近針對穩定性和性能對該擴展進行了重構。可以通過多種方法安裝這個新版本。該版本包含在易於安裝的 Zend Core for Oracle 包中,並包含在 PHP 源代碼和 Windows 二進制文件中。PHP 擴展社區庫 (PECL) 的源代碼中也有它,並且 http://pecl4win.PHP.Net/ext.php/PHP_oci8.dll 還提供 Windows 版的下載。

這個新擴展即可用於 PHP 4,也可用於 PHP 5。

查詢 Oracle 只需獲取並顯示數據。

$conn = oci_connect('hr', 'hrpw', '//localhost/XE');

$stid = oci_parse($conn, 'select city from locations');

oci_execute($stid);

oci_fetch_all($stid, $res);

oci_close($conn);

print '';

while ($row = oci_fetch_array($stid, OCI_RETURN_NULLS)) {

print '

';

foreach ($row as $item) {

print '

';

}

print '

';

}

print '

'.($item?HtmlentitIEs($item):'').'';

?>

該示例以 Oracle 的演示用戶 HR(Human Resources 的縮寫)的身份連接,並在 LOCATIONS 表中查找所有城市。

PHP 5 已經對 oci8 函數名進行了標准化。像 OCILogin() 這樣的 PHP 4 名稱已變為 oci_connect(),而舊名稱仍然可以使用。這將產生一個負面影響,即用戶在 PHP 手冊中為同一功能編寫的注釋將出現在兩個位置。這些注釋將分別出現在舊語法和新語法的頁面上。當函數存在同義詞時,需要同時檢查這兩個手冊頁以獲取某些好的、最新的用戶提示。

連接到 Oracle

要連接到 Oracle,可以使用 PHP 的 oci_connect() 調用:

$c = oci_connect($username, $passWord, $dbname)

每個 oci_connect() 連接均存儲在高速緩存中。當同一腳本中出現第二個 oci_connect() 時,將返回前一個高速緩存的連接。腳本完成時將清除該高速緩存。

Oci_new_connect() 提供了一個完全獨立的連接。連接之間相互獨立。這使您可以同時執行多個數據庫事務:

$c = oci_new_connect($username, $passWord, $dbname)

持久連接在 PHP 腳本結束時不會自動關閉。它們仍保持打開狀態,以便在其他腳本中重用:

$c = oci_pconnect($username, $passWord, $dbname)

當打開連接的開銷很大時,使用持久連接很有好處。開銷是否大取決於應用程序要求以及實現問題(如 web 服務器和數據庫是否位於同一主機中)。

持久連接的缺點是始終使用 Oracle 資源,即使在無人訪問應用程序或數據庫的情況下也是如此。如果 apache 創建了多個服務器進程,則每個進程將分別與數據庫建立一組連接。可以使用 PHP.ini 參數調節持久連接的資源使用。

oci8.max_persistent:該參數限制高速緩存的持久連接數。達到該限制時,所有 oci_pconnect() 調用均被視為 oci_connect() 調用。將該參數設置為 -1(默認值)表示沒有限制。

oci8.persistent_timeout:apache 進程保持空閒持久連接的時間(以秒為單位)。每當 PHP 腳本完成時,無論腳本是否調用 oci8 函數,都將執行到期檢查。將該參數設置為 -1(默認值)表示沒有超時。如果連接已過期,oci_pconnect() 將創建一個新連接。

oci8.ping_interval:oci8 在執行 oci_pconnect() 過程中執行 ping 操作之前經過的秒數。如果該參數設置為 0,則 PHP 將在每次調用 oci_pconnect() 時對數據庫執行 ping 操作。要禁用 ping,將該值設置為 -1。默認值為 60 秒。如果 ping 確定連接不可用,則將創建一個新連接。

良好的應用程序設計將透明地恢復大多數故障。盡管像 Oracle 這樣的系統比較穩定,但任何應用程序均存在一些潛在的故障點,其中包括網絡、硬件以及用戶操作(如關閉數據庫)。Oracle 本身可以經過配置來關閉空閒連接。DBA 可能已經使用 CREATE PROFILE IDLE_TIMEOUT 安裝了用戶配置文件。或者,Oracle Net 層可能已經使網絡超時。

Oci_pconnect() 將始終檢查 Oracle 客戶端設置,以便根據上次從服務器收到的任何響應判斷服務器是否可用。這是一個快速操作。另外設置 oci8.ping_interval 將對服務器執行物理 ping 操作,這將導致所謂的網絡“往返”,並且將對可伸縮性帶來不利影響。由於在連接檢查之間以及當您實際使用連接時,數據庫或某些數據仍有可能不可用,因此為了實現最高的可用性和可伸縮性,通常建議您不要使用 oci8.ping_interval,而是在應用程序代碼中進行錯誤恢復。

當然,越來越易於使用的 ping 功能還是為許多小型應用程序帶來了很多好處。

確保您了解應用程序連接的生存期。雖然應盡可能重用連接,但您也完全可以根據需要創建新連接以及關閉連接。每個連接都將占用一些 Oracle 內存,因此關閉空閒連接可以減少總負載。

連接字符串

最讓人感到困惑的當數連接字符串。常見的 Oracle 錯誤“ORA-12514 TNS:listener does not currently know of service requested in connect descriptor”即使花費很長時間仍難以解決。

DB 名稱可以為:

簡單連接字符串

完整連接字符串

tnsnames.ora 別名

簡單連接字符串

簡單連接字符串類似於 JDBC。它指定主機名、端口號和 Oracle 數據庫服務名稱:

//hostname:port/service_name

對於使用默認端口 1521 的 Oracle 數據庫特別版,只需使用“//localhost/XE”。

$c = oci_connect('hr', 'hrpw', '//localhost/XE');

必須具有 Oracle 10g 客戶端庫才能使用簡單連接語法。ZCO 具有相應的 Oracle 庫。

完整的硬編碼連接字符串

完整 Oracle Net 連接字符串提供了足夠的連接靈活性。

$db = MYDB2 = (DESCRIPTION =

(ADDRESS = (PROTOCOL = TCP)

(HOST = myMachine.mydomain)(PORT = 1521))

(CONNECT_DATA=

(SERVER = DEDICATED)

(SERVICE_NAME = MYDB.AU.Oracle.COM)))';

$c = oci_connect($un, $pw, $db);

如果存在疑問,請復制其他 Oracle 工具和用戶使用的連接字符串。

通過使用完整語法,可以實現像負載平衡這樣的 Oracle Net 特性,並可以調整包大小。簡單連接語法不具備這樣的靈活性。

Tnsnames.ora 文件中的網絡別名

可以將完整的連接字符串存儲在一個名為 tnsnames.ora 的文件中,並通過別名在 PHP 中引用它

# tnsnames.ora

MYDB2 = (DESCRIPTION =

(ADDRESS = (PROTOCOL = TCP)

(HOST = myMachine.mydomain)(PORT = 1521))

(CONNECT_DATA=

(SERVER = DEDICATED)

(SERVICE_NAME = MYDB.AU.Oracle.COM)))

在 PHP 中,可以使用以下代碼進行連接:

$c = oci_connect($un, $pw, 'MYDB2');

PHP 需要能找到 tnsnames.ora 文件來解析別名“MYDB2”。這是一個常見問題。

在“Oracle_HOME”樣式的安裝(例如,XE)中,默認的 tnsnames.ora 位於以下位置:

$Oracle_HOME/network/admin/tnsnames.ora

/usr/lib/oracle/xe/app/Oracle/product/10.2.0/server/network/admin/tnsnames.ora

無論是使用默認位置還是其他位置,apache 必須能夠在啟動時找到該目錄。通常情況下(包括在 ZCO 中),這通過設置 TNS_ADMIN 環境變量實現。

Oracle 環境變量

oci8 擴展始終需要查找 Oracle 庫和消息文件。找不到正確的文件將導致 PHP 返回 Oracle“ORA-12705:Cannot Access NLS data files or invalid environment specifIEd”。如果存在多個 Oracle 安裝,則可能發生沖突。ZCO 包含它自己的 Oracle 即時客戶端本地副本,該副本包含 Oracle 庫和消息,因此您不會看到該錯誤。

NLS_LANG(全球化)和 TNS_ADMIN(網絡)變量通常是 ZCO 所必需的。

必須設置啟動 apache 的環境中的環境變量,以便 oci8 擴展在首次加載時可以訪問這些值。在 PHP 腳本中不要使用 putenv() 設置環境變量。所有 oci8 函數的反映並不一致。它肯定不可移植。

ZCO 修改了 apachectl,添加了 LD_LIBRARY_PATH。(如果 Oracle 提供了以不同方式鏈接的即時客戶端,則未來版本的 ZCO 可能不需要該操作)。這使得可以重用 ZCO GUI 控制台來啟動 apache。

您可能需要使用 ZCO 的 TNS_ADMIN 和 NLS_LANG 執行類似操作,或者如果您手動啟動 apache,則在調用腳本中設置環境:

#!/bin/sh

TNS_ADMIN=/usr/local/apache/conf

export TNS_ADMIN

echo Starting apache

#export > /tmp/envvars

/usr/local/apache/bin/apachectl start

該示例假設 /usr/local/apache/conf/tnsnames.ora 存在。TNS_ADMIN 指向包含 tnsnames.ora 文件的目錄。

關閉連接

在每個腳本結束時,將自動關閉使用 oci_connect() 或 oci_new_connect() 打開的連接。您也可以調用以下代碼來顯式關閉連接:

oci_close($c);

將回滾任何未提交的數據。

如果長時間運行的腳本只用少量時間與數據庫交互,則您可能要關閉連接以將資源釋放給其他數據庫用戶使用。

oci_close() 無法關閉使用 oci_pconnect() 打開的連接。這與持久資源在其他 PHP 擴展中的工作方式類似。

Oci_close() 通過引用計數起作用。僅當完成所有連接引用時,才會實際關閉連接。在本示例中,$c1 和 $c2 是一個連接,但僅當腳本結束時,才會關閉數據庫連接。

$c1 = oci_connect('hr', 'hrpw', '//localhost/XE');

$c2 = oci_connect('hr', 'hrpw', '//localhost/XE');

do_query($c1, 'select user from dual');

oci_close($c1);

do_query($c1, 'select user from dual');

do_query($c2, 'select user from dual');

oci_close($c2);

在重構 oci8 之前,oci_close() 函數是一個無操作函數。即使在需要的情況下,您也無法顯式關閉連接。現在,這種情況發生了變化,但您可以在必要時通過在 PHP.ini 中設置 oci8.old_oci_close_semantics 來恢復為舊行為。將 oci8.old_oci_close_semantics 設置為 1 可以使 oci_close() 再次成為無操作函數。默認值 0 表示 oci_close() 將關閉連接。

執行語句

oci8 中的查詢遵循 Oracle 中常用的模型:分析、執行和獲取。類似 CREATE 和 INSERT 這樣的語句只需分析和執行。如今,分析實際上只是一個“准備”步驟,這是因為 Oracle 的實際分析操作會在執行階段執行。

您可以像在字符串中使用“%s”打印格式指示符那樣選擇將局部變量“綁定”到語句中。這樣做可以提高性能和安全性。

您也可以“定義”將結果存儲到的位置。大多數用戶讓 oci8 fetch 函數執行該操作。

可能的步驟包括:

分析 - 准備一個要執行的語句

綁定 - 可以有選擇地讓您綁定數據值(例如,在 WHERE 子句中)以便提高性能和安全性

定義 - 一個可選步驟,使您可以指定哪些 PHP 變量將保存結果。(不常見?)

執行 - 數據庫處理該命令並緩沖結果。

獲取 - 從數據庫中取回查詢結果。Oci8 提供了一些可供選擇的獲取語句。

沒有哪個 PHP 函數調用可以一次性執行以上所有操作,但在應用程序中創建一個這樣的函數也不難,它還允許您添加自定義的錯誤處理要求。

查詢

以下是 oci8 中的一個基本查詢:

$stid = oci_parse($c, 'select * from locations');

oci_execute($stid, OCI_DEFAULT);

oci_fetch_all($stid, $res);

確保在必要時使用雙引號:

$stid = oci_parse($c, "select * from locations where city = 'Sydney'");

oci8 包含一些 fetch 函數,PHP oci8 參考手冊對其進行了詳細說明。

oci_fetch_all():一次性獲取所有結果

oci_fetch_array():以您選擇的數組形式獲取下一行

oci_fetch_assoc():以關聯數組的形式獲取下一行

oci_fetch_object():以對象形式獲取新行

oci_fetch_row():以整數索引的數組形式獲取下一行

oci_fetch():與 oci_result()(返回給定字段的結果)一起使用

需要重復調用獲取單個行的函數:

$stid = oci_parse($c, "select city from locations");

oci_execute($stid, OCI_DEFAULT);

while ($res = oci_fetch_row($stid)) {

echo $res[0] ."
\n";

}

某些函數包含可更改其行為的可選參數,例如,oci_fetch_array() 提供了一些選項,用於指定是以關聯數組形式還是以數字索引數組形式(或同時以關聯數組和數字索引數組形式)返回結果。關聯數組使用大寫列名命名。

由於一些未知的歷史原因,某些 PHP 4 fetch 函數在默認情況下不返回 NULL 數據。對於這些函數,請指定您需要返回 NULL,否則結果可能不包含您選擇的所有列。

可以使用兩個 php.ini 參數調整 PHP 的總體查詢性能:

oci8.default_prefetch:當執行每個數據庫獲取操作時 Oracle 返回的記錄數。默認值為 10。調整該設置可以顯著提高返回大量行的查詢的性能。它每次返回盡可能多的數據,從而最大限度地降低了數據庫服務器的“往返”次數。Oracle 將數據高速緩沖在它的客戶端緩沖區中,並只向 PHP 提供 PHP 本身請求的行。

oci8.statement_cache_size:支持 OCI 客戶端語句高速緩存。默認值為 20 個語句。可以通過將該值設置為 0 來禁用高速緩存。客戶端語句高速緩存意味著甚至不需要將語句文本傳輸給數據庫,從而進一步減少了網絡通信量和服務器負載。高速緩存是一個純 Oracle 會話,因此當使用持久連接時,該特性通常很有用。

Insert/Update/Delete/Create/Drop

執行 CREATE 和 INSERT 等語句只需要進行分析和執行:

$s = oci_parse($c1, "create table i1test (col1 number)");

$r = oci_execute($s, OCI_DEFAULT);

$s = oci_parse($c1, "insert into i1test values (1)");

$r = oci_execute($s, OCI_DEFAULT);

只有一次性的應用程序配置部分才應使用 CREATE TABLE。某些用戶認為應用程序需要創建臨時表,而 Oracle 與其他數據庫的限制並不相同。

在應用程序運行之前創建一次臨時表。Tom Kyte 在 asktom.Oracle.com 中介紹了全局臨時表。

在 Oracle 數據庫中,創建和刪除表將自動提交所有未提交的數據。這種情況無法改變。

事務

就像任何其他關系應用程序一樣,使用事務保護數據完整性對於 PHP 同樣重要。但在極個別情況下,您需要提交所有數據,或根本不提交數據。

在前面的示例中,我們在執行代碼中指定了 OCI_EXECUTE 標志。

$r = oci_execute($s, OCI_DEFAULT);

oci_execute() 的默認模式為 OCI_COMMIT_ON_SUCCESS(其名稱顯示了它的功能)。而不必要的提交會影響數據庫性能,這是因為它將導致不必要的網絡通信量以及導致數據庫文件 I/O 的浪費。這就是為什麼首選 OCI_DEFAULT 的原因。

oci_execute() 的 PHP 手冊對此進行了簡要介紹:

使用 OCI_DEFAULT 模式時,您將創建一個事務。當您關閉連接或當腳本結束(以最先結束的為准)時,事務將自動回滾。您需要顯式調用 oci_commit() 提交事務,或調用 oci_rollback() 終止它。

在該示例中,如果不顯式提交,則在 PHP 腳本結束時將回滾第二行。要准確插入這兩行,就不應提交第一行,而是應在第二行之後提交 - 與該示例正好相反。

$s = oci_parse($c, "insert into i2test values ('row 1')");

$r = oci_execute($s);

$s = oci_parse($c, "insert into i2test values ('row 2')");

$r = oci_execute($s, OCI_DEFAULT);

錯誤處理

任何可靠的應用程序的錯誤處理均增加會復雜性並需要仔細的設計。期待著意外情況的出現。檢查所有返回值。

要獲取 Oracle 錯誤消息,必須將連接資源傳遞給 oci_error():

$c = oci_connect("hr", "hr", "//localhost/XE");

if (!$c) {

$e = oci_error(); // no resource passed

var_dump($e);

}

$stid = oci_parse($c, "select city from locations");

if (!$stid) {

$e = oci_error($c); // connection resource passed

var_dump($e);

}

$rc = oci_execute($stid, OCI_DEFAULT);

if (!$rc) {

$e = oci_error($stid); // statement resource passed

var_dump($e);

}

$rc = oci_fetch_all($stid, $results);

if (!$rc) {

$e = oci_error($stid); // statement resource passed

var_dump($e);

}

綁定變量

綁定變量類似於“%s”打印格式指定符。通過它們可以使用不同的變量值重新執行語句,從而獲得不同的結果。強烈建議您使用綁定。

它們可以提高數據庫總吞吐量。Oracle 可以對語句重用任何高速緩存的執行計劃,即使其他人最初執行了該計劃。

此外,綁定變量也是一個可以阻止 SQL 注入安全攻擊的重要方法。用戶數據通常被視為數據而非 SQL 語句的一部分。

$stid = oci_parse($c,

"select last_name from employees where employee_id = :eidbv");

$myeid = 101;

oci_bind_by_name($stid, ":EIDBV", $myeid);

oci_execute($stid, OCI_DEFAULT);

oci_fetch_all($stid, $res);

echo "Last name is:". $res['LAST_NAME'][0] ."\n";

// No need to re-parse

$myeid = 102;

oci_execute($stid, OCI_DEFAULT);

oci_fetch_all($stid, $res);

echo "Last name is:". $res['LAST_NAME'][0] ."\n";

綁定數據在調用 oci_execute() 時應可以訪問。在 sub 函數中使用局部變量可能會導致作用域問題。

除了向 Oracle 中傳入數據的“IN”綁定以外,還存在返回值的“OUT”綁定。它們通常用於從 PL/SQL 過程和函數返回值。

oci_bind_by_name() 函數使用可選的大小和數據類型參數。

綁定後的 PHP 數字與字符串之間進行相互轉換。這意味著在綁定變量中返回數字數據值時通常必須向 OCIBindByName() 提供 length 參數。該長度是將返回的位數。

在某種情況下,您可能決定不使用綁定變量。當語句包含綁定變量時,優化器不知道您最終要使用的值。如果數據很固定,則您可能要對值進行硬編碼。但如果數據是由用戶輸入,確保對其進行處理。

很多舊文檔在對 oci_bind_by_name() 的調用中使用“&”。不要這樣做。由於最新的 PHP 按引用調用清除了該語法,因此不建議使用該語法。我還發現該語法會導致一些問題。

PL/SQL 存儲過程

PL/SQL 是 Oracle 的過程語言。它最初以 ADA 為模型,是一種完善的強大語言。您可以直接在其中嵌入 SQL 語句。它在數據庫服務器中執行,這對 I/O 有一定的要求。

當決定是在客戶端中編寫 PHP 還是在服務器中編寫 PL/SQL 時,請考慮您的語言技能、通過網絡傳輸數據的成本以及代碼的可重用性。如果用 PL/SQL 編寫,則用任何工具或客戶端語言編寫的 Oracle 應用程序均可以重用此功能。某些功能將僅位於數據庫中,如事件觸發器。在 Oracle 中,可以創建在數據插入或用戶登錄等事件發生時引發的功能。

預先提供了一些 PL/SQL 程序包來簡化編碼以及一些實用程序(如 DBMS_JOB)來進行調度。您可以創建存儲過程、函數和程序包,以便可以無限制地擴展應用程序。通過 PL/SQL,您可以創建功能強大的應用程序。

要調用以前創建的 PL/SQL 過程,使用“匿名塊”。這只是一個內部包含 PL/SQL 語句的 BEGIN/END 對。在該示例中,只是一個過程調用。可以在該塊中使用任何所需 PL/SQL 語句。

$stid = oci_parse($c, "begin myproc('mydata', 123); end;");

oci_execute($stid, OCI_DEFAULT);

注意,“end”之後有一個分號,這與 SQL 語句的編寫方式不同。

PL/SQL REF CURSOR

REF CURSOR 是 PL/SQL 的另一個重要特性。您可以在一個 REF CURSOR 類型的變量中存儲一組查詢結果,並像傳遞普通變量那樣傳遞它。在 PHP 中,可以將 OCI_B_CURSOR 變量綁定到 PL/SQL 過程調用,並在普通的 fetch 循環中檢索結果集的行。

作為示例,我們創建的 PL/SQL 程序包將包含一個接受一個工作標識符、然後查詢執行該工作的員工的過程。該過程返回一個包含員工標識符和薪水的 REF CURSOR。

該程序包規范中提供了一個 ref cursor 類型以及過程簽名。程序包主體包含該功能的代碼。

CREATE OR REPLACE PACKAGE cv_types AS

TYPE EmpInfoTyp is REF CURSOR;

PROCEDURE EmpInfoRpt (jid IN VARCHAR, emp_cv IN OUT EmpInfoTyp);

END cv_types;

/

CREATE OR REPLACE PACKAGE BODY cv_types AS

PROCEDURE EmpInfoRpt (jid IN VARCHAR, emp_cv IN OUT EmpInfoTyp) AS

BEGIN

OPEN emp_cv FOR SELECT EMPLOYEE_ID, SALARY

FROM EMP_DETAILS_VIEW WHERE JOB_ID=jid;

END;

END;

/

在 PHP 中,我們可以按如下所示使用此 PL/SQL 過程:

$job_id = 'SA_MAN';

$stmt = "BEGIN cv_types.EmpInfoRpt(:jid, :rc); END;";

$stid = oci_parse($c, $stmt);

oci_bind_by_name($stid, ':jid', $job_id);

$refcur = oci_new_cursor($c); // pass the connection

oci_bind_by_name($stid, ':rc', $refcur, -1, OCI_B_CURSOR);

// Execute the call to EmpInfoRpt()

oci_execute($stid);

// Execute and fetch from the cursor

oci_execute($refcur);

echo '';

while($row = oci_fetch_assoc($refcur)) {

echo '

';

foreach ($row as $c) {

echo "

";

}

echo '

';

}

echo '

$c';

大型對象 (LOB)

Oracle 字符大對象 (CLOB) 和二進制大對象 (BLOB) 列(以及 PL/SQL 變量)可以包含大量的數據。有很多方法可以創建這些對象來優化 Oracle 存儲。此外,還預先提供了一個程序包 DBMS_LOB,通過它可以輕松地在 PL/SQL 中操作這些對象。

與使用 REF CURSOR 相似,我們告訴 PHP 我們需要一個 LOB 類型的變量,然後將其綁定到 SQL 或 PL/SQL 語句中。然後,我們有一些可以用於訪問該數據的特殊 oci8 函數。

將 LOB 數據上載到表中:

$myv = 'a very large amount of binary data';

$lob = oci_new_descriptor($c, OCI_D_LOB);

$stid = oci_parse($c,

'INSERT INTO mybtab (blobid, blobdata) '

. 'VALUES(123, EMPTY_BLOB()) RETURNING blobdata INTO :blobdata');

oci_bind_by_name($stid, ':BLOBDATA', $lob, -1, OCI_B_BLOB);

oci_execute($stid, OCI_DEFAULT);

$lob->save($myv);

我們通過 PHP 描述符操作 LOB。這些 LOB 映射到 Oracle LOB 定位器。

如果通過 Web 表單上載了 lob,則可以使用 $lob->savefile($filename) 直接從上載的目錄文件中上載它。可以使用 upload_max_filesize 在 PHP.ini 中設置所允許的上載文件的最大大小。

獲取 LOB 時,oci8 將返回 LOB 描述符,並通過使用 load() 或 read() 方法檢索數據:

$query = 'SELECT blobdata FROM mybtab WHERE blobid = 123';

$stmt = oci_parse ($conn, $query);

oci_execute($stmt, OCI_DEFAULT);

$arr = oci_fetch_assoc($stmt);

$result = $arr['BLOBDATA']->load();

LOB 描述符中的一些其他方法允許定位到指定偏移量、將數據直接導出到文件、清除數據以及復制或比較 LOB。

以下代碼片段顯示了定位到結果描述符中的第 10 個位置,然後將後面的 50 個字節存儲在 $result 中

$arr['BLOBDATA']->seek(10, OCI_SEEK_SET);

$result = $arr['BLOBDATA']->read(50);

CLOB 的用法與 BLOB 的用法基本相同。綁定類型變成了 OCI_B_CLOB,且表必須明確包含一個 CLOB 列。

Oracle 集合

Oracle 手冊中提到:“集合是一個同一類型元素的有序組。”它們是有效的數組。

與 LOB 相似,集合由使用 oci_new_collection() 分配的集合資源上的方法操作。

在一個簡單的電子郵件地址簿演示(由 Oracle 的 Charles Poulsen 創建)中,創建了兩個 VARRAY,一個用於用戶名稱數組,另一個用於電子郵件地址數組。VARRAY(根據 Oracle 手冊的描述,它是可變大小數組 (variable-size array) 的縮寫)使用序列化數字作為訪問一組固定數量元素的下標。

SQL> drop table emails;

SQL> create table emails (

user_id varchar2(10),

frIEnd_name varchar2(20),

email_address varchar2(20));

SQL> create or replace type email_array as

varray(100) of varchar2(20);

/

SQL> create or replace type frIEnd_array as

varray(100) of varchar2(20);

/

SQL> create or replace procedure update_address_book(

p_user_id in varchar2,

p_friend_name frIEnd_array,

p_email_addresses email_array)

is

begin

delete from emails where user_id = p_user_id;

for i in 1 .. p_email_addresses.count loop

insert into emails (user_id, frIEnd_name, email_address)

values (p_user_id, p_frIEnd_name(i),

p_email_addresses(i));

end loop;

end update_address_book;

/

update_address_book() 過程遍歷地址集合的所有元素並插入每個元素。

在 PHP 中,我們創建集合變量並使用 append() 方法向每個數組中添加元素。通過綁定為 OCI_B_NTY(“有名類型”),我們可以向 PL/SQL 過程參數中傳遞集合。

$user_name = 'cjones';

$frIEnds_names = array('alison', 'aslam');

$frIEnds_emails = array('[email protected]', '[email protected]');

$friend_coll = oci_new_collection($c, 'FRIEND_ARRAY');

$email_coll = oci_new_collection($c, 'EMAIL_ARRAY');

for ($i=0; $i < count($frIEnds_names); $i++) {

$friend_coll->append($frIEnds_names[$i]);

$email_coll->append($frIEnds_emails[$i]);

}

$stid = oci_parse($c,

"begin update_address_book(:name, :frIEnds, :emails); end;");

oci_bind_by_name($stid, ':name', $user_name);

oci_bind_by_name($stid, ':friends', $frIEnd_coll, -1, OCI_B_NTY);

oci_bind_by_name($stid, ':emails', $email_coll, -1, OCI_B_NTY);

oci_execute($stid);

其他 PHP 集合方法允許訪問或復制集合中的數據。

PHP 5.1.2 通過一個新函數 oci_bind_array_by_name() 增強了對集合的支持。該函數與 helper PL/SQL 函數一起使用時對插入非常有效。我們可以綁定一個包含所有數據的 PHP 數組並使用一個 oci_execute() 將其發送給數據庫。

SQL> drop table mytab;

SQL> create table mytab(name varchar2(20));

SQL> create or replace package mypkg as

type arrtype is table of varchar2(20) index by binary_integer;

procedure myproc(p1 in out arrtype);

end mypkg;

/

SQL> create or replace package body mypkg as

cursor cur is select name from mytab;

procedure myproc(p1 in out arrtype) is

begin

for i in 1 .. p1.count loop

insert into mytab values (p1(i));

end loop;

end myproc;

end mypkg;

/

要將 PHP 數組插入到 MYTAB 中,使用:

$s = "BEGIN mypkg.myproc(:c1); END;";

$stid = oci_parse($c, $s);

$array = array("abc", "def", "ghi", "jkl", "mno");

oci_bind_array_by_name($stid, ":c1", $array, 5, -1, SQLT_CHR);

oci_execute($stid, OCI_DEFAULT);

oci_commit();

oci_bind_array_by_name() 函數與 oci_bind_by_name() 相似。它不但接收數據長度上限,而且還接收數組中的元素個數。在本示例中,元素數量為 5,數據長度為 -1(即使用字符數據的實際長度)。

插入的數據為:

SQL> select * from mytab;

NAME

--------------------

abc

def

ghi

jkl

mno

可以綁定一些其他 Oracle 類型。PHP 手冊鏡像只獲取 oci_bind_array_by_name() 文檔。通過讀取 CVS 中的 oci8 樹下的自動測試獲取信息源。這些測試也與 PHP 源代碼打包在一起。

全球化

Web 應用程序全球化需要仔細的規劃。必須使用正確的字符集表示數據,必須正確轉換和編碼 Html 頁面,並應留意用戶期望的慣例。Oracle 數據庫特別版兩日速成以及 PHP 開發人員指南對全球化進行了全面的概述。

Oracle 數據庫是使用指定字符集創建的。PHP 可以通過設置 NLS_LANG 環境變量選擇它自己的字符集。Oracle 客戶端(即 PHP)全球化設置還指定了默認值,如區域設置的正確日期格式、Oracle 錯誤消息使用的語言以及語言排列順序。應在啟動 Web 服務器的環境中設置 NLS_LANG。它的格式為:

_.

例如,德國一位運行使用 Unicode 的應用程序的德語用戶應將 NLS_LANG 設置為:

GERMAN_GERMANY.AL32UTF8

還可以使用 oci_connect() 可選的第四個參數按連接設置字符集。該字符集是一個包含 Oracle 字符集名稱的字符集(例如,“ja16euc”)。

$c = oci_connect("hr", "hr", "//localhost/XE", 'ja16euc');

當未指定或為 NULL 時,則使用 NLS_LANG 環境變量設置。

客戶端字符集決定了 Oracle 如何對從數據庫傳輸到 PHP 的數據進行轉換。如果字符集不等價,則可能錯誤地轉換某些數據。

應由您的應用程序來正確處理返回的數據(通常使用 PHP 的 mb_string 功能)。

使用 XML

請您自行研究 SQL 和 PL/SQL。最大限度地重用已經存在的功能。Tom Kyte 廣受歡迎的 asktom.Oracle.com 提供了大量有用的信息。

Oracle 的一般指導原則是讓數據庫管理數據,並通過網絡傳輸最少量的信息。不要將數據從數據庫傳遞到 PHP,從而避免不必要的後期處理。數據是企業的核心資產。所有應用程序均應一致地處理數據。在應用程序層與數據庫之間維護一個瘦接口也是一個不錯的編程實踐。

正則表達式、XML 函數、分析函數、自動事務以及空間功能也是有用的數據庫特性的一些例證。

Oracle 和 PHP 5 均提供了出色的 XML 功能(允許使用大量作用域處理信息)。Oracle 的所有版本均包含所謂的 Oracle XML DB(或 XDB),即數據庫的 XML 功能。

創建表後,可以使用線性 LOB 格式或根據 XML 模式的結構存儲 XML。

一個有用的特性是可以自動將關系 SQL 表檢索為 XML:

$query =

'SELECT XMLELEMENT("Employees",

XMLELEMENT("Name", employees.last_name), XMLELEMENT("Id", employees.employee_id)) as result

FROM employees

WHERE employee_id > 200';

$stid = oci_parse($c, $query);

oci_execute($stid, OCI_DEFAULT);

while ($row = oci_fetch_row($stid))

foreach ($row as $item)

echo HtmlentitIEs($item)." ";

注意 XML 查詢的引用。

PL/SQL 程序包 DBMS_XMLGEN() 是另一種基於關系數據創建 XML 的方法。使用 DBMS_XMLGEN() 的查詢返回一個 CLOB 列,因此需要將初始結果視為 LOB 描述符:

$query = "select dbms_xmlgen.getXML('

select first_name

from employees

where department_id = 30') XML

from dual";

$stid = oci_parse($c, $query);

oci_execute($stid, OCI_DEFAULT);

$res = oci_fetch_row($stid);

$mylob = $res[0]->load(); // treat result as a LOB descriptor

$mylob 中的值為:

Den

Alexander

Shelli

Sigal

Guy

Karen

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved