oci_fetch_array

(PHP 5, PHP 7, PHP 8, PECL OCI8 >= 1.1.0)

oci_fetch_array将查询的下一行作为关联数组或数字数组返回

说明

oci_fetch_array(资源 $statement, 整数 $mode = OCI_BOTH | OCI_RETURN_NULLS): 数组|false

返回一个包含查询的下一结果集行的数组。每个数组条目对应于行的列。此函数通常在循环中调用,直到它返回 false,表示不再存在行。

如果 statement 对应于返回 Oracle 数据库隐式结果集的 PL/SQL 块,那么将连续获取所有集合中的行。如果 statement 是由 oci_get_implicit_resultset() 返回的,那么将只返回一个子查询的行的子集。

有关 OCI8 扩展执行的数据类型映射的详细信息,请参阅 驱动程序支持的数据类型

参数

statement

一个有效的 OCI8 语句标识符,由 oci_parse() 创建并由 oci_execute() 执行,或一个 REF CURSOR 语句标识符。

也可以是 oci_get_implicit_resultset() 返回的语句标识符。

mode

可选的第二个参数可以是以下常量的任何组合

oci_fetch_array() 模式
常量 说明
OCI_BOTH 返回一个包含关联和数字索引的数组。这与 OCI_ASSOC + OCI_NUM 相同,也是默认行为。
OCI_ASSOC 返回一个关联数组。
OCI_NUM 返回一个数字数组。
OCI_RETURN_NULLS null 字段创建元素。元素值将是 PHP null
OCI_RETURN_LOBS 返回 LOB 的内容,而不是 LOB 描述符。

默认的 modeOCI_BOTH

使用加号运算符“+”一次指定多个模式。

返回值

返回一个包含关联和/或数字索引的数组。如果 statement 中没有更多行,则返回 false

默认情况下,LOB 列作为 LOB 描述符返回。

DATE 列作为格式化为当前日期格式的字符串返回。默认格式可以使用 Oracle 环境变量(如 NLS_LANG)更改,或者通过先前执行的 ALTER SESSION SET NLS_DATE_FORMAT 命令更改。

Oracle 的默认不区分大小写的列名在结果数组中将具有大写关联索引。区分大小写的列名将具有使用确切列大小写的数组索引。使用 var_dump() 在结果数组上验证每个查询要使用的适当大小写。

表名不包含在数组索引中。如果查询包含两个名称相同的不同列,请使用 OCI_NUM 或向查询添加列别名以确保名称唯一性,请参见示例 #7。否则,将只通过 PHP 返回一列。

示例

示例 #1 oci_fetch_array()OCI_BOTH

<?php

$conn
= oci_connect('hr', 'welcome', 'localhost/XE');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

$stid = oci_parse($conn, 'SELECT department_id, department_name FROM departments');
oci_execute($stid);

while ((
$row = oci_fetch_array($stid, OCI_BOTH)) != false) {
// 使用大写列名作为关联数组索引
echo $row[0] . " and " . $row['DEPARTMENT_ID'] . " are the same<br>\n";
echo
$row[1] . " and " . $row['DEPARTMENT_NAME'] . " are the same<br>\n";
}

oci_free_statement($stid);
oci_close($conn);

?>

示例 #2 oci_fetch_array()OCI_NUM

<?php

/*
在运行之前,创建表:
CREATE TABLE mytab (id NUMBER, description CLOB);
INSERT INTO mytab (id, description) values (1, 'A very long string');
COMMIT;
*/

$conn = oci_connect('hr', 'welcome', 'localhost/XE');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

$stid = oci_parse($conn, 'SELECT id, description FROM mytab');
oci_execute($stid);

while ((
$row = oci_fetch_array($stid, OCI_NUM)) != false) {
echo
$row[0] . "<br>\n";
echo
$row[1]->read(11) . "<br>\n"; // 这将输出 DESCRIPTION 的前 11 个字节
}

// 输出为:
// 1
// A very long

oci_free_statement($stid);
oci_close($conn);

?>

示例 #3 oci_fetch_array()OCI_ASSOC

<?php

/*
在运行之前,创建表:
CREATE TABLE mytab (id NUMBER, description CLOB);
INSERT INTO mytab (id, description) values (1, 'A very long string');
COMMIT;
*/

$conn = oci_connect('hr', 'welcome', 'localhost/XE');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

$stid = oci_parse($conn, 'SELECT id, description FROM mytab');
oci_execute($stid);

while ((
$row = oci_fetch_array($stid, OCI_ASSOC)) != false) {
echo
$row['ID'] . "<br>\n";
echo
$row['DESCRIPTION']->read(11) . "<br>\n"; // 这将输出 DESCRIPTION 的前 11 个字节
}

// 输出为:
// 1
// A very long

oci_free_statement($stid);
oci_close($conn);

?>

示例 #4 oci_fetch_array()OCI_RETURN_NULLS

<?php

$conn
= oci_connect('hr', 'welcome', 'localhost/XE');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

$stid = oci_parse($conn, 'SELECT 1, null FROM dual');
oci_execute($stid);
while ((
$row = oci_fetch_array ($stid, OCI_ASSOC)) != false) { // 忽略 NULL 值
var_dump($row);
}

/*
上面的代码打印:
array(1) {
[1]=>
string(1) "1"
}
*/

$stid = oci_parse($conn, 'SELECT 1, null FROM dual');
oci_execute($stid);
while ((
$row = oci_fetch_array ($stid, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { // 获取 NULL 值
var_dump($row);
}

/*
上面的代码打印:
array(2) {
[1]=>
string(1) "1"
["NULL"]=>
NULL
}
*/

?>

示例 #5 oci_fetch_array()OCI_RETURN_LOBS

<?php

/*
在运行之前,创建表:
CREATE TABLE mytab (id NUMBER, description CLOB);
INSERT INTO mytab (id, description) values (1, 'A very long string');
COMMIT;
*/

$conn = oci_connect('hr', 'welcome', 'localhost/XE');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

$stid = oci_parse($conn, 'SELECT id, description FROM mytab');
oci_execute($stid);

while ((
$row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_LOBS)) != false) {
echo
$row['ID'] . "<br>\n";
echo
$row['DESCRIPTION'] . "<br>\n"; // 这包含了整个 DESCRIPTION
// 在循环中,在第二次获取之前释放大型变量可以减少 PHP 的峰值内存使用量
unset($row);
}

// 输出为:
// 1
// A very long string

oci_free_statement($stid);
oci_close($conn);

?>

示例 #6 oci_fetch_array() 与区分大小写的列名

<?php

/*
运行前,创建表:
CREATE TABLE mytab ("Name" VARCHAR2(20), city VARCHAR2(20));
INSERT INTO mytab ("Name", city) values ('Chris', 'Melbourne');
COMMIT;
*/

$conn = oci_connect('hr', 'welcome', 'localhost/XE');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

$stid = oci_parse($conn, 'select * from mytab');
oci_execute($stid);
$row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS);

// 因为 'Name' 被创建为区分大小写的列,所以数组索引使用相同的 case。但是大写 'CITY' 必须
// 用于区分大小写列的索引
print $row['Name'] . "<br>\n"; // 打印 Chris
print $row['CITY'] . "<br>\n"; // 打印 Melbourne

oci_free_statement($stid);
oci_close($conn);

?>

示例 #7 oci_fetch_array() 带有重复名称的列

<?php

/*
运行前,创建表:
CREATE TABLE mycity (id NUMBER, name VARCHAR2(20));
INSERT INTO mycity (id, name) values (1, 'Melbourne');
CREATE TABLE mycountry (id NUMBER, name VARCHAR2(20));
INSERT INTO mycountry (id, name) values (1, 'Australia');
COMMIT;
*/

$conn = oci_connect('hr', 'welcome', 'localhost/XE');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

$sql = 'SELECT mycity.name, mycountry.name
FROM mycity, mycountry
WHERE mycity.id = mycountry.id'
;
$stid = oci_parse($conn, $sql);
oci_execute($stid);
$row = oci_fetch_array($stid, OCI_ASSOC);
var_dump($row);

// 输出只包含一个 "NAME" 条目:
// array(1) {
// ["NAME"]=>
// string(9) "Australia"
// }

// 要查询重复的列名,使用 SQL 列别名,例如 "AS ctnm":
$sql = 'SELECT mycity.name AS ctnm, mycountry.name
FROM mycity, mycountry
WHERE mycity.id = mycountry.id'
;
$stid = oci_parse($conn, $sql);
oci_execute($stid);
$row = oci_fetch_array($stid, OCI_ASSOC);
var_dump($row);

// 输出现在包含两个选定的列:
// array(2) {
// ["CTNM"]=>
// string(9) "Melbourne"
// ["NAME"]=>
// string(9) "Australia"
// }


oci_free_statement($stid);
oci_close($conn);

?>

示例 #8 oci_fetch_array() 带有 DATE

<?php

$conn
= oci_connect('hr', 'welcome', 'localhost/XE');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

// 为此连接设置日期格式。
// 出于性能原因,请考虑在触发器中或使用环境变量来更改格式
$stid = oci_parse($conn, "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD'");
oci_execute($stid);

$stid = oci_parse($conn, 'SELECT hire_date FROM employees WHERE employee_id = 188');
oci_execute($stid);
$row = oci_fetch_array($stid, OCI_ASSOC);
echo
$row['HIRE_DATE'] . "<br>\n"; // 打印 1997-06-14

oci_free_statement($stid);
oci_close($conn);

?>

示例 #9 oci_fetch_array() 带有 REF CURSOR

<?php
/*
创建 PL/SQL 存储过程如下:

CREATE OR REPLACE PROCEDURE myproc(p1 OUT SYS_REFCURSOR) AS
BEGIN
OPEN p1 FOR SELECT * FROM all_objects WHERE ROWNUM < 5000;
END;
*/

$conn = oci_connect('hr', 'welcome', 'localhost/XE');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

$stid = oci_parse($conn, 'BEGIN myproc(:rc); END;');
$refcur = oci_new_cursor($conn);
oci_bind_by_name($stid, ':rc', $refcur, -1, OCI_B_CURSOR);
oci_execute($stid);

// 执行返回的 REF CURSOR 并像语句标识符一样从中获取
oci_execute($refcur);
echo
"<table border='1'>\n";
while ((
$row = oci_fetch_array($refcur, OCI_ASSOC+OCI_RETURN_NULLS)) != false) {
echo
"<tr>\n";
foreach (
$row as $item) {
echo
" <td>".($item !== null ? htmlentities($item, ENT_QUOTES) : "&nbsp;")."</td>\n";
}
echo
"</tr>\n";
}
echo
"</table>\n";

oci_free_statement($refcur);
oci_free_statement($stid);
oci_close($conn);

?>

示例 #10 使用 LIMIT 类查询的 oci_fetch_array() 分页

<?php

$conn
= oci_connect('hr', 'welcome', 'localhost/XE');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

// 查找数据库版本
preg_match('/Release ([0-9]+)\./', oci_server_version($conn), $matches);
$oracleversion = $matches[1];

// 这是您要“分页”的查询
$sql = 'SELECT city, postal_code FROM locations ORDER BY city';

if (
$oracleversion >= 12) {
// 利用 Oracle 12c OFFSET / FETCH NEXT 语法
$sql = $sql . ' OFFSET :offset ROWS FETCH NEXT :numrows ROWS ONLY';
} else {
// 较旧的 Oracle 版本需要一个嵌套查询,从 $sql 中选择一个子集
// 或者,如果在开发时已知 SQL 语句,请考虑使用 row_number() 函数代替此
// 嵌套解决方案。在生产环境中,请注意使用连接避免 SQL 注入问题。
$sql = "SELECT * FROM (SELECT a.*, ROWNUM AS my_rnum
FROM (
$sql) a
WHERE ROWNUM <= :offset + :numrows)
WHERE my_rnum > :offset"
;
}

$offset = 0; // 跳过这些行
$numrows = 5; // 返回 5 行
$stid = oci_parse($conn, $sql);
oci_bind_by_name($stid, ':numrows', $numrows);
oci_bind_by_name($stid, ':offset', $offset);
oci_execute($stid);

while ((
$row = oci_fetch_array($stid, OCI_ASSOC + OCI_RETURN_NULLS)) != false) {
echo
$row['CITY'] . " " . $row['POSTAL_CODE'] . "<br>\n";
}

// 输出为:
// Beijing 190518
// Bern 3095
// Bombay 490231
// Geneva 1730
// Hiroshima 6823

oci_free_statement($stid);
oci_close($conn);

?>

示例 #11 使用 Oracle 数据库隐式结果集的 oci_fetch_array()

<?php

$conn
= oci_connect('hr', 'welcome', 'localhost/pdborcl');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

// 需要 OCI8 2.0(或更高版本)和 Oracle 数据库 12c(或更高版本)
// 也请参见 oci_get_implicit_resultset()
$sql = 'DECLARE
c1 SYS_REFCURSOR;
BEGIN
OPEN c1 FOR SELECT city, postal_code FROM locations WHERE ROWNUM < 4 ORDER BY city;
DBMS_SQL.RETURN_RESULT(c1);
OPEN c1 FOR SELECT country_id FROM locations WHERE ROWNUM < 4 ORDER BY city;
DBMS_SQL.RETURN_RESULT(c1);
END;'
;

$stid = oci_parse($conn, $sql);
oci_execute($stid);

// 注意:oci_fetch_all 和 oci_fetch 不能以这种方式使用
echo "<table>\n";
while ((
$row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) != false) {
echo
"<tr>\n";
foreach (
$row as $item) {
echo
" <td>".($item!==null?htmlentities($item, ENT_QUOTES|ENT_SUBSTITUTE):"&nbsp;")."</td>\n";
}
echo
"</tr>\n";
}
echo
"</table>\n";

// 输出为:
// Beijing 190518
// Bern 3095
// Bombay 490231
// CN
// CH
// IN

oci_free_statement($stid);
oci_close($conn);

?>

注释

注意:

对于使用不区分大小写名称创建的标准 Oracle 列,关联数组索引需要大写。

注意:

对于返回大量行的查询,可以通过增加 oci8.default_prefetch 或使用 oci_set_prefetch() 来显著提高性能。

注意:

oci_fetch_array() 的速度比 oci_fetch_assoc()oci_fetch_row() 略慢,但更灵活。

另请参见

添加注释

用户贡献注释 2 个注释

Maxwell_Smart at ThePentagon dot com
22 年前
当使用 OCI_RETURN_LOBS 获取 BFILE(使用目录存储)时,用户需要对目录进行读取操作。(GRANT READ on DIRECTORY <目录名称> TO <用户>)否则,您将收到一个难以理解的错误。警告:OCILobFileOpen:ORA-22285:在 ... 的 ... 行上进行 FILEOPEN 操作时,目录或文件不存在。
<BR>
创建目录的用户会自动获得 READ WITH THE GRANT OPTION 权限。
junk at netburp dot com
23 年前
这里有一个关于 rowid 的提示。

不要忘记 oracle 函数

"rowidtochar" 和 "chartorowid"

"select rowidtochar(rowid) as FOO from table ...."

当您想在表单或链接中传递 rowid 时,这就是
唯一的方法。
To Top