原文地址:https://blogs.oracle.com/opal/entry/converting_ref_cursor_to_pipe

REF CURSORs are common in Oracle's stored procedural language PL/SQL. They let you pass around a pointer to a set of query results.

However in PHP, PDO_OCI doesn't yet allow fetching from them. And fetching from REF CURSORS in OCI8 is not as fast as doing a normal query. This is because of two architectural decisions: OCI8 doesn't use the preferred Oracle style of "array fetching". Instead it uses "prefetching", but prefetching from REF CURSORS isn't supported by Oracle for various reasons (including that array fetching is available and recommended....)

One workaround, when you can't rewrite the PL/SQL code to do a normal query, is to write a wrapper function that pipes the output.

For this example, the "fixed" procedure that you can't change is:

create or replace procedure myproc(p1 out sys_refcursor) as
begin
open p1 for select last_name from employees;
end;

The wrapper function follows the performance tip in 12-14 of Tuning PL/SQL Applications for Performance and uses a BULK COLLECT:

create or replace package myplmap as
type outtype is record ( -- structure of the ref cursor in myproc
last_name varchar2()
);
type outtype_set is table of outtype;
function maprctopl return outtype_set pipelined;
end;
/
show errors create or replace package body myplmap as
function maprctopl return outtype_set pipelined is
outrow outtype_set;
p_rc sys_refcursor;
rlim pls_integer := ; -- fetch batches of rows at a time
begin
myproc(p_rc); -- call the original procedure
loop
fetch p_rc bulk collect into outrow limit rlim;
exit when outrow.count = ;
for i in .. outrow.count loop
pipe row (outrow(i));
end loop;
end loop;
end maprctopl;
end myplmap;

The PHP OCI8 code to query the pipelined function is:

<?php

$c = oci_connect('hr', 'hrpwd', '//localhost/XE');

$s = oci_parse($c, "select * from table(myplmap.maprctopl())");
oci_execute($s);
oci_fetch_all($s, $res);
var_dump($res); ?>

You could use this query in PDO_OCI too.

I found it doubled the performance of smallish tests with a local database (from small time to even smaller time). The change is more dramatic from a distant, remote database. With a query returning a large number of rows it dropped the runtime to 35 seconds from about 24 minutes.

This tip will appear in the next edition of the Underground PHP and Oracle Manual.

Update: Prefetching from REF CURSORS is supported in Oracle 11gR2. See Oracle Database 11gR2 Enhancements for PHP

Converting REF CURSOR to PIPE for Performance in PHP OCI8 and PDO_OCI的更多相关文章

  1. Report_报表中Ref Cursor数据源的概念和用法(案例)

    2014-06-22 Created By BaoXinjian

  2. REF CURSOR和CURSOR

    REF CURSOR DECLARE TYPE TY_EMP_CUR IS REF CURSOR; V_Emp_Cur TY_EMP_CUR; V_Id EMP.ID%TYPE; BEGIN OPEN ...

  3. Entity Framework 5.0.0 Function Import 以及 ODP. NET Implicit REF CURSOR Binding使用简介

    源代码 概要: 1,说明如何使用Entity Framework中的function import功能. 2,说明如何使用ODP.NET的隐式REF CURSOR绑定(implicit REF CUR ...

  4. Oracle ref cursor和sys_refcursor

    1. 自定义 ref cursor 和 sys_refcursor; 2. sys_refcursor 做为参数传递结果集; 3. ref cursor 做为参数传递结果集; 1. 自定义 ref c ...

  5. oracle中REF Cursor用法

    from:http://www.111cn.net/database/Oracle/42873.htm 1,什么是 REF游标 ? 动态关联结果集的临时对象.即在运行的时候动态决定执行查询. 2,RE ...

  6. PLSQL中显示Cursor、隐示Cursor、动态Ref Cursor差别

    一.显式cursor 显式是相对与隐式cursor而言的,就是有一个明白的声明的cursor.显式游标的声明类似例如以下(具体的语法參加plsql ref doc ): cursor cursor_n ...

  7. ORACLE中RECORD、VARRAY、TABLE、IS REF CURSOR 的使用及实例详解

    ORACLE中RECORD.VARRAY.TAB.IS REF CURSOR LE的使用及实例详解 create or replaceprocedure PRO_RECORD_ROW_TAB_EXAM ...

  8. oracle sys_refcursor用法和ref cursor区别

    --创建过程,参数为sys_refcursor,为out型 create or replace procedure aabbsys_refcursor(o out sys_refcursor) is ...

  9. oracle 存储过程及REF CURSOR的使用

    基本使用方法及示例 1.基本结构: CREATE OR REPLACE PROCEDURE 存储过程名字 (参数1 IN NUMBER,参数2 IN NUMBER) AS 变量1 INTEGER := ...

随机推荐

  1. 给ajax表单提交数据前面加上实体名称

    有时候我们后台做了一个引用类型例如: 下面的实体以C#为例 public class Order{ public string orderId{get;set;} public OrderItem o ...

  2. VMware 安装Arch Linux记录

    首先说明一下我的环境. 1.VMware Workstation 10.0.1 build-1379776 2.archlinux-2014.02.01-dual.iso 首先建立虚拟机,其他的不提了 ...

  3. Redis 实现队列http://igeekbar.com/igeekbar/post/436.htm

    场景说明: ·用于处理比较耗时的请求,例如批量发送邮件,如果直接在网页触发执行发送,程序会出现超时 ·高并发场景,当某个时刻请求瞬间增加时,可以把请求写入到队列,后台在去处理这些请求 ·抢购场景,先入 ...

  4. js escape 与php escape

    javascript有编码函数escape()和对应的解码函数unescape(),而php中只有个urlencode和urldecode,这个编码和解码函数对encodeURI和encodeURIC ...

  5. GB2312码表

    GB2312码表 code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F A1A0 . . · ˉ ˇ ¨ " 々 — - | … ‘ ’ ...

  6. Skyline开发3-没有注册类0x80040154

    原生64位程序 我们现在使用的操作系统多为64位系统,其中大部分用的还是32位的软件. 64位软件优点是:可以进行更大范围的整数运算:可以支持更大的内存:除做科学运算的时候取得更好的性能外,不能提高其 ...

  7. 使用jsp内置对象request获取表单提交中文内容乱码的解决办法

    page1.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pag ...

  8. Xcode missing file or .png is missing from working copy

    当不小心在工程文件中删掉文件时.有可能会提示 .xxx   is missing from working copy 有可能是SVN引起的.删掉这个文件就好了 如果是单个文件.进入Terminal 相 ...

  9. ubuntu建立快捷方式

    拷贝一下文件到新的文件里 [Desktop Entry]Categories=Development;Comment[zh_CN]=Comment=Exec=/usr/local/idea-IU-17 ...

  10. 很好的vmware目录

    http://www.globalknowledge.com/training/course.asp?pageid=9&courseid=18023&country=United+St ...