分享
 
 
 

Php操作oracle数据库指南

王朝oracle·作者佚名  2006-12-16
窄屏简体版  字體: |||超大  

Php操作oracle数据库指南

作者:rookie 来源:phpx.com

本人由于工作关系使用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);

?>

忘了说了,显示CLOB里的数据也要象BLOB一样使用:$result[1]->load() 这样的形式,因为clob是对象类型,无法象别的类型数据可直接显示。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有