DBMNG数据库管理与应用

科学是实事求是的学问,来不得半点虚假。
当前位置:首页 > Oracle > 驱动连接

PHP连接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

Php代码
  1. $dbconn=OCILogon("scott","tiger","test");    
  2. $sql ="select * from emp";   
  3. $stmt = OCIParse($dbconn, $sql);    
  4. if(!$stmt) {    
  5. echo "

    ERROR - Could not parse SQL statement.

    ";    
  6. exit;    
  7. }    
  8. OCIExecute($stmt);    
  9. while( OCIFetchInto($stmt, &$result_array) )    
  10. {    
  11. echo    
  12.   
  13. "EMPno=$result_array[0];Ename=$result_array[1];JOB=$result_array[2];MGR=$result_array[3]
    ";    
  14. }   
  15. ?>   
ERROR - Could not parse SQL statement. "; 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]
"; } ?>

 

二、用PHP执行Oracle存储过程
(1)用sqlplus连接后,建立一个存储过程:

Sql代码
  1. CREATE OR REPLACE PROCEDURE inoutdemo (    
  2. par_in IN VARCHAR2,   
  3. par_in_out IN OUT VARCHAR2,   
  4. par_out OUT VARCHAR2)    
  5. IS  
  6. BEGIN  
  7. par_out := par_in;   
  8. par_in_out := par_in || ' ' || par_in_out;   
  9. END;  
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手册

Php代码
  1. $conn=OCILogon("scott","tiger","test");    
  2. $stmt = OCIParse($conn,"BEGIN inoutdemo(:in,:inout,:out); END;");   
  3. OCIBindByName($stmt,":in",$in,32);   
  4. OCIBindByName($stmt,":inout",$inout,32);   
  5. OCIBindByName($stmt,":out",$out,32);   
  6.   
  7. $in = "Hello ";   
  8. $inout = "World!";   
  9.   
  10. OCIExecute($stmt);   
  11. echo "

    ";   
  12. echo "in=".$in."
    ";   
  13. echo "inout=".$inout."
    ";   
  14. echo "out=".$out."
    ";   
  15. ?>  
$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 "

"; echo "in=".$in."
"; echo "inout=".$inout."
"; echo "out=".$out."
"; ?>

 

三、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的话,可这样写:

Php代码
  1. $conn=OCILogon($username,$password,$sid);   
  2. //first sentence  
  3. $Sql = "insert into tablename values()";   
  4. $stmt=OCIParse($conn,$Sql);   
  5. $result=OCIExecute($stmt, OCI_DEFAULT);   
  6. if (!$result) {   
  7. OCIRollback($conn);//不成功则回滚   
  8. OCIFreeStatement($stmt); //释放资源  
  9. OCILogoff($conn);   
  10. }   
  11.   
  12. //second sentence  
  13. $Sql = " update tablename set..";   
  14. $stmt=OCIParse($conn,$Sql);   
  15. $result=OCIExecute($stmt, OCI_DEFAULT);   
  16. if (!$result) {   
  17. OCIRollback($conn);//不成功则回滚   
  18. OCIFreeStatement($stmt); //释放资源  
  19. OCILogoff($conn);   
  20. }   
  21.   
  22.   
  23. OCICommit($conn);//如果都成功则提交  
  24. OCIFreeStatement($stmt); //释放资源  
  25. OCILogoff($conn);  
$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中

Sql代码
  1. CREATE TABLE PICTURES (    
  2. ID NUMBER,    
  3. IMGTYPE, VARCHAR2(60),   
  4. DESCRIPTION VARCHAR2(100),    
  5. PICTURE BLOB    
  6. );   
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()

Php代码
  1. if($lob-〉savefile($lob_upload)){    
  2. OCICommit($conn);    
  3. echo "上传成功〈br〉";    
  4. }else{    
  5. echo "上传失败〈br〉";    
  6. }    
  7.   
  8. //方法二:用SAVE的方法保存  
  9. //$fp = fopen($lob_upload, "r");  
  10. //$File->save(fread($fp, filesize($lob_upload)));  
  11. //fclose($fp );  
  12.   
  13. //释放LOB对象   
  14. OCIFreeDesc($lob);    
  15. OCIFreeStatement($stmt);    
  16. OCILogoff($conn);    
  17. ?>   
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):

Php代码
  1. $conn = OCILogon($username, $password, $sid);    
  2. $stmt = OCIParse($conn,"SELECT imgtype,picture FROM PICTURES WHERE ID=$pictureid");    
  3. if (OCIFetchInto($stmt, $result))    
  4. {    
  5. Header("Content-type: ".$result[0]);   
  6. echo $result[1]->load();   
  7. }   
  8. //可用strlen($result[1]->load()) 查看图片的大小以确定图片是否正确存入到数据库。  
  9.   
  10. ?>  
load(); } //可用strlen($result[1]->load()) 查看图片的大小以确定图片是否正确存入到数据库。 ?>

 

在需要显示图片的地方只要:
放在Oracle LOB中的图片

就能显示图片了
有的网上文章写用返回LOB值而非描述符的方法显示,我没有试成功,大家可以试下
代码如下:

Php代码
  1. if (OCIFetchInto($stmt, $result, OCI_ASSOC+OCI_RETURN_LOBS))    
  2. {    
  3. echo "Content-type: " . StripSlashes($result[imgtype]);    
  4. echo StripSlashes($result[picture]);    
  5. }   
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的方法来实现。
//如:

Php代码
  1. $stmt = OCIParse($conn,"INSERT INTO table (id, clobtext) VALUES (text.NEXTVAL,,    
  2.   
  3. EMPTY_CLOB()) RETURNING clobtext INTO :clob");    
  4.   
  5.   
  6. $sql = "begin tempclobtest_package.saveclob(:clob); end;";   
  7.   
  8. $clob = OCINewDescriptor($conn, OCI_D_LOB);    
  9.   
  10. $stmt = OCIParse($conn, $sql);   
  11.   
  12. OCIBindByName ($stmt,':clob', &$clob , -1,OCI_B_CLOB );   
  13.   
  14. if(!OCIExecute($stmt, OCI_DEFAULT)) {print_r(OCIError($stmt));}   
  15. else{echo "提交成功";}   
  16.   
  17. if($clob->save($clobtext))   
  18. {   
  19. OCICommit($conn);   
  20. echo "提交成功";   
  21. }   
  22. else  
  23. {   
  24. print_r(OCIError($stmt));   
  25. }   
  26.   
  27. //释放资源  
  28. $clob->free();   
  29. OCIFreeStatement($stmt);   
  30. ?>  
$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); ?>

 

转自:http://namezhou.iteye.com/blog/724528

本站文章内容,部分来自于互联网,若侵犯了您的权益,请致邮件chuanghui423#sohu.com(请将#换为@)联系,我们会尽快核实后删除。
Copyright © 2006-2023 DBMNG.COM All Rights Reserved. Powered by DEVSOARTECH            豫ICP备11002312号-2

豫公网安备 41010502002439号