免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4607 | 回复: 0
打印 上一主题 下一主题

PHP下调用oracle存储函数实现教程 [复制链接]

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-08-03 16:27 |只看该作者 |倒序浏览
很久没发贴了,最近心得贴出以于大家共同分享。

PHP下调用oracle存储函数实现教程(To invoke stored functions or procedures of oracle in PHP)

参考资料:
oracle官方网站:http://www.oracle.com/
oracle官方文档:http://www.oracle.com/technology ... p-oracle-manual.pdf
PHP手册:http://cn2.php.net/manual/zh/ref.oci8.php

一.安装PHP的oracle扩展
PHP的oracle扩展网上资料还算比较多,最权威是是oracle官方的教程:《Installing PHP and the Oracle 10g Instant Client for Linux and Windows》,地址:http://www.oracle.com/technology ... te_php_instant.html
现在就我自己的亲身体会来谈一谈我是如何操作的。
Linux平台:
1.下载两个软件包:Instant Client Package - Basic和nstant Client Package - SDK,截止本文最新包版本是10.2.0.3
因为我的系统是redhat as4,所以需要下载Instant Client for Linux x86版本。
这两个文件分别是racle-instantclient-basic-10.2.0.3-1.i386.rpm和oracle-instantclient-devel-10.2.0.3-1.i386.rpm
当然你也可以下载zip版本,将他们解压到同一目录,例如/usr/lib/oracle/10.2.0.3/client/。rpm包的话安装起来比较省心。
rpm -Uvh oracle-instantclient-basic-10.2.0.3-1.i386.rpm
rpm -Uvh oracle-instantclient-devel-10.2.0.3-1.i386.rpm
2.重新编译PHP,添加oracle扩展。

  1. ./configure --with-oci8-instant-client=/usr/lib/oracle/10.2.0.3/client/lib --enable-sigchild
复制代码

这里需要注意一点的是:
oracle官方说在php4.3.9-4.3.10由于存在一个bug,需要先下载一个补丁:http://www.oracle.com/technology ... i8ic_buildpatch.txt,将内容存为一个文件,例如php_oci8ic_buildpatch,然后给ext/oci8/config.m4文件打上补丁:
patch -u config.m4 php_oci8ic_buildpatch
如果在此之前系统上已有PHP4.3.9,那么还需要

  1. cd php-4.3.9
  2. rm -rf autom4te.cache config.cache
  3. ./buildconf --force
复制代码

再做./configure操作
完成后make && make install
3.设置oracle环境变量

  1. #!/bin/sh
  2. APACHEHOME=/home/apache
  3. LD_LIBRARY_PATH=/usr/lib/oracle/10.2.0.3/client/lib:${LD_LIBRARY_PATH}
  4. TNS_ADMIN=/home
  5. export LD_LIBRARY_PATH TNS_ADMIN
  6. echo Starting Apache
  7. $APACHEHOME/apachectl start
复制代码

4.验证是否安装成功
重新启动apache,然后在web目录下建立一个新的文件:info.php,内容如下

  1. <?php
  2. phpinfo();
  3. ?>
复制代码

访问一下这个文件,看看是否有oci的扩展。如果有,则说明安装成功,否则失败。
[注意]我仅在php4下安装成功,在php5的怎么也安装不上。目前原因还不清楚。

Windows平台:
windows平台下的安装较为简单,如果是PHP5下的Instant Client 方式,请直接参考《Enabling the PHP OCI8 Extension on Windows》这一节,我没有试验。
对于PHP4,直接修改php.ini文件,将php_oci8.dll扩展打开(就是将它前面的;去掉)就行。然后重启apache(cgi模式可不用重启)

二.连接oracle
对于一个新手来说,oracle的安装使用难度非常高。很多概念与常用的mysql完全不同。
在PHP手册上,连接oracle的脚本非常简单:

  1. $conn = OCILogon('hr', 'hr', 'orcl');
  2. if (!$conn) {
  3.   $e = ocierror();
  4.   print htmlentities($e['message']);
  5.   exit;
  6. }
复制代码

事实上,安装好PHP的oci扩展后,这个脚本完全不能工作,因为oci_connect()的第三个参数是连接字符串,需要得到一个文本文件nsnames.ora
形如:

  1. ORCL_130 =
  2.   (DESCRIPTION =
  3.     (ADDRESS_LIST =
  4.       (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.12.130)(PORT = 1521))
  5.     )
  6.     (CONNECT_DATA =
  7.       (SID = ORCL)
  8.     )
  9.   )
复制代码

Linux下,这个文件放在TNS_ADMIN指定的目录下,windows下,这个文件放在PHP安装目录下就可以。
需要指出的是:在windows下,你不可以使用
$conn = OCILogon('username', 'passwd', '//192.168.12.130:1521/ORCL');
这种方式连接到oracle,具体原因不明。
此外,PHP5开始使用新的oci扩展函数名,很多在php3和php4时代的函数名都做了更改,如果你使用的是php4,请使用老的函数名。这给很多初学者造成了不小的麻烦,因为很多的资料都是新的函数名了。

三.调用oracle的存储过程
本为调用oracle的存储过程是一件非常简单的事的,但,这里需要指出的是,oracle的stored procedures和stored functions是两种不同的方法,中文翻译时常有人认为是一样的,我们可以把它们分别称为存储过程和存储函数,对于pl/sql来说可能调用方法一致,没什么两样,但如果你使用php的oci扩展这类api时,会发现很大不同,如果你用存储过程的方法来调用一个存储函数,你可以会得到一个存储过程不存在或未定义的错误。
在oracle官方的手册上我们可以找到这两者调用的不同例子:
存储过程调用

  1. <?php
  2. $c = oci_connect('hr', 'hrpwd', '//localhost/XE');
  3. $s = oci_parse($c, "call myproc('Chris', 123)");
  4. oci_execute($s);
  5. ?>
复制代码



  1. <?php
  2. $c = oci_connect('hr', 'hrpwd', '//localhost/XE');
  3. $s = oci_parse($c, "begin myproc('Alison', 456); end;");
  4. oci_execute($s);
  5. ?>
复制代码

存储函数的调用如下

  1. <?php
  2. $c = oci_connect('hr', 'hrpwd', '//localhost/XE');
  3. $s = oci_parse($c, "begin :ret := mypack.myfunc(123); end;");
  4. oci_bind_by_name($s, ':ret', $r, 20);
  5. oci_execute($s);
  6. echo "Name is: ".$r;
  7. ?>
复制代码

我们可以看到,存储函数的调用使用了返回值=函数名(参数)这种方式(:ret := mypack.myfunc(123)
此外,
oci_bind_by_name()函数在使用时需要注意,如果要绑定一个抽象数据类型(LOB/ROWID/BFILE),需要先用 oci_new_descriptor() 函数分配空间,具体见PHP手册。
如果需要绑定的是SQLT_RSET(游标类型,则需要oci_new_cursor()在指定的连接上分配一个新的语句句柄,5.0之前用ocinewcursor())

附:PHP4下一个返回游标类型的例子

  1. <?php
  2. $conn        = OCILogon('username', 'passwd', 'ORCL_130');
  3. $user        = 'test01';
  4. $passwd        = '000000';
  5. $zList        = ocinewcursor($conn);
  6. $stmt        = OCIParse($conn, "begin :n_RetCode := mypack.myfunc($user, $$passwd, :zList); end;");
  7. OCIBindByName($stmt, ':n_RetCode',$n_RetCode,-1);
  8. OCIBindByName($stmt, ':zList',$zList,-1,OCI_B_CURSOR);
  9. OCIExecute($stmt);

  10. OCIExecute($zList);
  11. $nrows        = ocifetchstatement($zList, $results);
  12. if ($nrows > 0) {
  13.    echo "<table border=\"1\">\n";
  14.    echo "<tr>\n";
  15.    foreach ($results as $key => $val) {
  16.       echo "<th>$key</th>\n";
  17.    }
  18.    echo "</tr>\n";

  19.    for ($i = 0; $i < $nrows; $i++) {
  20.       echo "<tr>\n";
  21.       foreach ($results as $data) {
  22.          echo "<td>$data[$i]</td>\n";
  23.       }
  24.       echo "</tr>\n";
  25.    }
  26.    echo "</table>\n";
  27. } else {
  28.    echo "No data found<br />\n";
  29. }

  30. OCIFreeStatement($stmt);
  31. OCILogoff($conn);

  32. ?>
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP