Php操作oracle資料庫指南-本人原創,經驗總結,不能不看

來源:互聯網
上載者:User
oracle|資料|資料庫|原創 本人由於工作關係使用Oracle資料庫,發現這裡用的人不多,但時常發現有人提的關於PHP操作ORACLE資料庫的問題得不到回答,我也曾問過幾個,但也無人響應,因此決定把本人在工作中積攢起來的一些技巧、經驗奉獻出來,希望對使用oracle資料庫的人有所協助。
一、配置環境:
訪問Oracle8以上的資料庫需要用到Oracle8 Call-Interface(OCI8)。這個擴充模組需要Oracle8 的用戶端函數庫,因此需要你要串連遠程Oracle資料庫的話,還要裝上Oracle的用戶端軟體-可以到Oracle網站上免費下載- http://www.oracle.com,這是許多初學者常常忽略的,因此如果看了這篇文章,就不要在論壇上再提“為什麼我串連不上Oracle資料庫”之類的問題了。
(1)首先確認安裝了Oracle8i用戶端,然後用net8 assistant(用戶端軟體提供)建立一個服務命名,注意服

務名是oracle資料庫的sid,可查詢initsid檔案裡的server_names得到。
(2)在php.ini中把 ;extension=php_oci8.dll 前面的注釋符號“;”去掉,使php能夠載入支援oracle的模組

。並把php_oci8.dll拷貝到你的windows2000 server安裝目錄下的system32子目錄。如d:\winnt\system32,重

新啟動你的機器。
(3)寫個測試檔案試一下是否能正確串連(假如服務名sid是test):
這裡scott使用者是Oracle內建的無須你自己建立了,只要把下面這個檔案放到你的WEB根目錄就可以了。如果顯

示到資料庫中的資料,則說明串連正常,如果不行,你還要檢查前幾步有哪些地方做錯了。
test.php
<?
$dbconn=OCILogon("scott","tiger","test");
$sql ="select * from emp";
$stmt = OCIParse($dbconn, $sql);
if(!$stmt) {
echo "<h1>ERROR - Could not parse SQL statement.</h1>";
exit;
}
OCIExecute($stmt);
while( OCIFetchInto($stmt, &$result_array) )
{
echo

"EMPno=$result_array[0];Ename=$result_array[1];JOB=$result_array[2];MGR=$result_array[3]<BR>";
}
?>

二、用PHP執行Oracle預存程序
(1)用sqlplus串連後,建立一個預存程序:
CREATE OR REPLACE PROCEDURE inoutdemo (
par_in IN VARCHAR2,
par_in_out IN OUT VARCHAR2,
par_out OUT VARCHAR2)
IS
BEGIN
par_out := par_in;
par_in_out := par_in || ' ' || par_in_out;
END;
(2)PHP檔案:
sptest.php
<?
//:in是輸入變數;:inout是輸入輸出變數;:out是輸出變數,具體解釋請參考Oracle的PL/SQL手冊
$conn=OCILogon("scott","tiger","test");
$stmt = OCIParse($conn,"BEGIN inoutdemo(:in,:inout,:out); END;");
OCIBindByName($stmt,":in",$in,32);
OCIBindByName($stmt,":inout",$inout,32);
OCIBindByName($stmt,":out",$out,32);

$in = "Hello ";
$inout = "World!";

OCIExecute($stmt);
echo "<BR><BR>";
echo "in=".$in."<BR>";
echo "inout=".$inout."<BR>";
echo "out=".$out."<BR>";
?>

三、Oracle資料庫的分頁
Oracle雖然不象Mysql有limit可用,十分方便,但也有自己的處理方法,它特殊的rownum對分頁有很重要的作

用。分頁可有很多種方法,其中最常用的是用minus。
如要顯示n1-n2記錄可寫為:
(1)SELECT * FROM tablename WHERE rownum <= n2 minus SELECT * FROM tablename WHERE rownum < n1
注意:該語句不能使用order by,否則報錯。
(2)把指標下移的辦法如:
其中:$page是當前頁;$pagesize是每頁顯示的記錄數
for($i=0;$i<($page-1)*$pagesize;$i++)
{
@ocifetch($stmt);
}
然後再用ocifetch($stmt)取出的資料就是你要顯示的記錄了
(3)對於有複雜查詢語句並用order by來排序的,可使用下面方法解決:
SELECT TABLE_NAME,TABLE_TYPE FROM( SELECT ROWNUM ROWSEQ,X.* FROM (SELECT * FROM CAT ORDER BY

TABLE_TYPE) X) WHERE ROWSEQ BETWEEN n1+1 AND n2;
本人最喜歡的是第三種,也推薦大家使用,非常方便的啊。呵呵。
其它方法就不介紹了,很麻煩,使用了Oracle遊標之類的東東,不太適合PHP使用。

四、特殊字元的插入處理
對於一些字元如單引號'在Oracle裡是不能用addslashes處理的,但可以使用Oracle的CHR函數或再加個單引號


如:SQL>insert into table values('it'||chr(39)||'s a test'));
或 SQL>insert into table values('it''s a test'));
顯示:
it's a test.

五、PHP和Oracle的交易處理
OCIExecute()函數:int OCIExecute ( int statement [, int mode] )
第二個參數mode共有兩個:預設為OCI_COMMIT_ON_SUCCESS,可省略。OCI_DEFAULT 表示用事務(Transation)

提交,不自動認可。
如果你在程式中如果有兩個操作資料庫的語句需要同時成功執行,有一個失敗就要rollback的話,可這樣寫:

$conn=OCILogon($username,$password,$sid);
//first sentence
$Sql = "insert into tablename values()";
$stmt=OCIParse($conn,$Sql);
$result=OCIExecute($stmt, OCI_DEFAULT);
if (!$result) {
OCIRollback($conn);//不成功則復原
OCIFreeStatement($stmt); //釋放資源
OCILogoff($conn);
}

//second sentence
$Sql = " update tablename set..";
$stmt=OCIParse($conn,$Sql);
$result=OCIExecute($stmt, OCI_DEFAULT);
if (!$result) {
OCIRollback($conn);//不成功則復原
OCIFreeStatement($stmt); //釋放資源
OCILogoff($conn);
}


OCICommit($conn);//如果都成功則提交
OCIFreeStatement($stmt); //釋放資源
OCILogoff($conn);



六、用PHP操縱Oracle的LOB類型的資料(含圖片的儲存與顯示處理)
對PHP程式員來講,Oracle最令人頭痛的莫過於使用LOB來處理圖片了。
1。PHP操作BLOB:
先建立一個表用於儲存圖片。使用者上傳的圖片檔案存放到BLOB中
CREATE TABLE PICTURES (
ID NUMBER,
IMGTYPE, VARCHAR2(60),
DESCRIPTION VARCHAR2(100),
PICTURE BLOB
);
如果要實現ID的自動增加,再建一個SEQUENCE:
CREATE SEQUENCE PIC_SEQ;

PHP程式-插入部分:
<?
$conn=OCILogon($username,$password,$sid);
//在這裡要注意的兩點:一是用EMPTY_BLOB()函數。這是Oracle的內部函
//數,返回一個LOB的定位器。在插入LOB時,只能用這個辦法先產生一個
//空的LOB定位器,然後對這個定位器進行操作。EMPTY_BLOB()函數是針
//對BLOB類型的,對應於CLOB的是EMPTY_CLOB()。二是RETURNING後面的
//部分,把picture返回,讓PHP的OCI函數能夠處理。
$stmt = OCIParse($conn,"INSERT INTO PICTURES (id, imgtype,description, picture) VALUES

(PIC_SEQ.NEXTVAL, '$imgtype','$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, -1, 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〉";
}

//方法二:用SAVE的方法儲存
//$fp = fopen($lob_upload, "r");
//$File->save(fread($fp, filesize($lob_upload)));
//fclose($fp );

//釋放LOB對象
OCIFreeDesc($lob);
OCIFreeStatement($stmt);
OCILogoff($conn);
?>
小技巧:在sqlplus裡可用select dbms_lob.getlength(picture) from pictures;查看檔案是否已存入到資料

庫或在PHP程式裡用strlen()函數查看。

PHP程式-顯示部分(getpicture.php):
<?
$conn = OCILogon($username, $password, $sid);
$stmt = OCIParse($conn,"SELECT imgtype,picture FROM PICTURES WHERE ID=$pictureid");
if (OCIFetchInto($stmt, $result))
{
Header("Content-type: ".$result[0]);
echo $result[1]->load();
}
//可用strlen($result[1]->load()) 查看圖片的大小以確定圖片是否正確存入到資料庫。

?>

在需要顯示圖片的地方只要:
<IMG SRC="getpicture.php?pictureid=99" ALT="放在Oracle LOB中的圖片">

就能顯示圖片了
有的網上文章寫用返回LOB值而非描述符的方法顯示,我沒有試成功,大家可以試下
代碼如下:
if (OCIFetchInto($stmt, $result, OCI_ASSOC+OCI_RETURN_LOBS))
{
echo "Content-type: " . StripSlashes($result[imgtype]);
echo StripSlashes($result[picture]);
}

2。PHP操作CLOB:
Oracle有一種資料類型叫VARCHAR2,用來表示不定長的字串。VARCHAR2也是Oracle公司推薦使用的類型。但

使用VARCHAR2有個問題:最大隻能表示4000個字元,也就相當於2000個漢字。如果你的程式中某個字串的長

度要大於2000個漢字,用VARCHAR2就不能滿足要求了。這時候,你可以嘗試使用CLOB。CLOB和BLOB的最大長度

是4GB。

下面是樣本(參考了PHP英文版的手冊):
<?
//要儲存的文字
$clobtext="different dr2";

//db connection
$conn = OCIlogon("user","pw","TNS");

//這裡原例子使用了一個預存程序,你也可以用上面操作BLOB的方法來實現。
//如:$stmt = OCIParse($conn,"INSERT INTO table (id, clobtext) VALUES (text.NEXTVAL,,

EMPTY_CLOB()) RETURNING clobtext INTO :clob");


$sql = "begin tempclobtest_package.saveclob(:clob); end;";

$clob = OCINewDescriptor($conn, OCI_D_LOB);

$stmt = OCIParse($conn, $sql);

OCIBindByName ($stmt,':clob', &$clob , -1,OCI_B_CLOB );

if(!OCIExecute($stmt, OCI_DEFAULT)) {print_r(OCIError($stmt));}
else{echo "提交成功";}

if($clob->save($clobtext))
{
OCICommit($conn);
echo "提交成功";
}
else
{
print_r(OCIError($stmt));
}

//釋放資源
$clob->free();
OCIFreeStatement($stmt);
?>


相關文章

Cloud Intelligence Leading the Digital Future

Alibaba Cloud ACtivate Online Conference, Nov. 20th & 21st, 2019 (UTC+08)

Register Now >

11.11 Big Sale for Cloud

Get Unbeatable Offers with up to 90% Off,Oct.24-Nov.13 (UTC+8)

Get It Now >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。