《PHP+Oracle(OCI) 初步》中講了如何用PHP中的OCI函數來連接Oracle數據庫
執行一些SQL查詢及關閉數據庫連接
本文將講述另一個難度稍大的問題
用PHP的OCI函數來操縱Oracle的LOB字段
閱讀本文需要《PHP+Oracle(OCI) 初步》一文中的知識
用過Oracle的人都知道Oracle有一種數據類型叫VARCHAR用來表示不定長的字符串VARCHAR也是Oracle公司推薦使用的類型但使用VARCHAR有個問題最大只能表示個字符也就相當於個漢字如果你的程序中某個字符的值要大於個漢字用VARCHAR就不能滿足要求了這時候你有兩個選擇一是用多個VARCHAR來表示二是用LOB字段這裡我們來看看第二個辦法
先來大體了解一下Oracle的LOB字段Oracle的LOB類型分為三種BLOBCLOB和BFILECLOB稱為字符LOBBLOB和BFILE是用來存儲二進制數據的CLOB和BLOB的最大長度是GB它們把值存放在Oracle數據庫中BFILE和BLOB類似但它把數據放在外部的文件中所以它又稱為外部BLOB(External BLOB)
我想我們對MYSQL應該都不會陌生MYSQL中也有類似的數據類型如TEXT和BLOB在PHP的MYSQL函數中對TEXT/BLOB的操作是直接的就象其它類型的數據一樣但在Oracle中情況就不一樣了Oracle把LOB當作一種特殊的數據類型來處理在操作上不能用常規的方法比如不能在INSERT語句中直接把值插入到LOB字段中也不能用LIKE進行查找
下面就通過幾個例子來說明如何用PHP的OCI函數來插入取出和查詢LOB數據
一插入
不能直接用INSERT語句向LOB字段中插入值一般情況下有如下的幾步
.先分析一個INSERT語句返回一個LOB的描述符
.用OCI函數生成一個本地的LOB對象
.將LOB對象綁定到LOB描述符上
.執行INSERT語句
.給LOB對象賦值
.釋放LOB對象和SQL語句句柄
下面的這個例子是把用戶上傳的圖片文件存放到BLOB(或BFILE中操作稍有不同)中
首先要建一個表結構如下
CREATE TABLE PICTURES (
ID NUMBER
DESCRIPTION VARCHAR()
MIME VARCHAR()
PICTURE BLOB
);
如果要實現ID的自動增加再建一個SEQUENCE:
CREATE SEQUENCE PIC_SEQ;
然後是用來處理數據的PHP程序代碼
<?php
//建立Oracle數據庫連接
$conn = OCILogon($user $password $SID);
//提交SQL語句給Oracle
//在這裡要注意的兩點一是用EMPTY_BLOB()函數這是Oracle的內部函數返回一個LOB的定位符在插入LOB時只能用這個辦法先生成一個空的LOB定位符然後對這個定位符進行操作EMPTY_BLOB()函數是針對BLOB類型的對應於CLOB的是EMPTY_CLOB()二是RETURNING後面的部分把picture返回讓PHP的OCI函數能夠處理
$stmt = OCIParse($connINSERT INTO PICTURES (id description picture)
VALUES (pic_seqNEXTVAL $description $lob_upload_type EMPTY_BLOB()) RETURNING picture INTO :PICTURE);
//生成一個本地LOB對象的描述符注意函數的第二個參數OCI_D_LOB表示生成一個LOB對象其它可能的還有OCI_D_FILE和OCI_D_ROWID分別對應於BFILE和ROWID對象
$lob = OCINewDescriptor($conn OCI_D_LOB);
//將生成的LOB對象綁定到前面SQL語句返回的定位符上
OCIBindByName($stmt :PICTURE &$lob OCI_B_BLOB);
OCIExecute($stmt);
//向LOB對象中存入數據因為這裡的源數據是一個文件所以直接用LOB對象的savefile()方法LOB對象的其它方法還有save()和load()分別用來保存和取出數據但BFILE類型只有一個方法就是save()
if($lob>savefile($lob_upload)){
OCICommit($conn);
echo 上傳成功<br>;
}else{
echo 上傳失敗<br>;
}
//釋放LOB對象
OCIFreeDesc($lob);
OCIFreeStatement($stmt);
OCILogoff($conn);
?>
還有一個要注意的地方LOB字段的值最少要個字符所以在save()或savefile()之前要確保值不能為空否則Oracle會出錯
二取出
對一個LOB中取出數據有兩種辦法一是生成一個LOB對象然後綁定到一條SELECT語句返回的定位符上再用LOB對象的load()方法取出數據二是直接用PHP的OCIFetch***函數第一種方法比第二種方法要麻煩得多所以我直接說說第二種方法還是用上面的表
<?php
$conn = OCILogon($user $password $SID);
$stmt = OCIParse($connSELECT * FROM PICTURES WHERE ID=$pictureid);
OCIExecute($stmt);
//秘密就在PCIFetchInfo的第三個參數上OCI_RETURN_LOBS第三個參數是FETCH的模式如果OCI_RETURN_LOBS就直接把LOB的值放到結果數組中而不是LOB定位符也就不用LOB對象的load()方法了
if (OCIFetchInto($stmt $result OCI_ASSOC+OCI_RETURN_LOBS))
{
echo Contenttype: StripSlashes($result[MIME]);
echo StripSlashes($result[PICTURE]);
}
OCIFreeStatement($stmt);
OCILogoff($conn);
?>
這個程序用來顯示放在LOB中的數據(圖片)調用方法(假設腳本名是getpicturephp)
<IMG SRC=getpicturephp?pictureid= ALT=放在Oracle LOB中的圖片>
三查詢
前面已經提了下對於Oracle的LOB字段是不能用LIKE進行匹配的怎麼辦呢?其實並不復雜Oracle有一個匿名的程序包叫DBMS_LOB裡面有所有的操作LOB所需的過程
假設有象這樣一個表:
CREATE TABLE ARTICLES (
ID NUMBER
TITLE VARCHAR()
CONTENT CLOB
);
文章的內容放在CONTENT字段中
現在我們要找出所以內容中包含PHP中文用戶的文章可以這麼來做
<?php
$conn = OCILogon($user $password $SID);
//WHERE子句中用了DBMS_LOBINSTR過程它有四個參數前面兩個分別表示LOB的定位符(可以直接用字段表示)和要查找的字符串後面兩個分別表示開始的偏移量和出現的次數要注意的是必須判斷它的返回值也就是要大於
$stmt = OCIParse($connSELECT * FROM ARTICLES WHERE DBMS_LOBINSTR(CONTENT PHP中文用戶 ) > );
OCIExecute($stmt);
if (OCIFetchInto($stmt $result OCI_ASSOC+OCI_RETURN_LOBS))
{
}
OCIFreeStatement($stmt);
OCILogoff($conn);
?>
Oracle還提供了許多用來操作LOB數據的過程如LENGTH SUBSTR等等至於它們的詳細用法可以考慮Oracle的開發手冊
關於對Oracle數據庫中的LOB類型的數據的操作就說這麼多了由於我接觸Oracle時間不長本文中可能還會有錯誤歡迎大家批評指正
From:http://tw.wingwit.com/Article/program/PHP/201311/21377.html