ConFoo 2025

oci_parse

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

oci_parse実行のために Oracle の文をパースする

説明

oci_parse(resource $connection, string $sql): resource|false

connection を使って sql をパースし、ステートメント ID を返します。この ID は、oci_bind_by_name(), oci_execute() や他の関数で使用されます。

ステートメント ID を解放するには、 oci_free_statement() を使うか、あるいは 変数に null を代入します。

パラメータ

connection

oci_connect()oci_pconnect() あるいは oci_new_connect() が返す Oracle 接続 ID。

sql

SQL あるいは PL/SQL ステートメント。

SQL の最後にセミコロン (";") をつけては いけません。一方、PL/SQL ステートメントの最後はセミコロン (";") を つけなければなりません

戻り値

成功した場合にステートメントハンドル、あるいはエラー時に false を返します。

例1 oci_parse() での SQL 文の例

<?php

$conn
= oci_connect('hr', 'welcome', 'localhost/XE');

// パースします。SQL 文の最後にはセミコロンがないことに注意しましょう
$stid = oci_parse($conn, 'SELECT * FROM employees');
oci_execute($stid);

echo
"<table border='1'>\n";
while (
$row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) {
echo
"<tr>\n";
foreach (
$row as $item) {
echo
" <td>" . ($item !== null ? htmlentities($item, ENT_QUOTES) : "&nbsp;") . "</td>\n";
}
echo
"</tr>\n";
}
echo
"</table>\n";

?>

例2 oci_parse() での PL/SQL の例

<?php

/*
この PHP プログラムを実行する前に、SQL*Plus や SQL Developer で
ストアドプロシージャを作っておきます

CREATE OR REPLACE PROCEDURE myproc(p1 IN NUMBER, p2 OUT NUMBER) AS
BEGIN
p2 := p1 * 2;
END;

*/

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

$p1 = 8;

// PL/SQL プログラムをパースするには、文字列の最後にセミコロンが必要です
$stid = oci_parse($conn, 'begin myproc(:p1, :p2); end;');
oci_bind_by_name($stid, ':p1', $p1);
oci_bind_by_name($stid, ':p2', $p2, 40);

oci_execute($stid);

print
"$p2\n"; // 16 と表示します

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

?>

注意

注意:

この関数は sql を検証 しませんsql が有効な SQL あるいは PL/SQL 文かどうかを検証する唯一の方法 - それは実行することです。

参考

add a note

User Contributed Notes 5 notes

up
1
interloper at ukr dot net
9 years ago
If you want using PL/SQL in variable:

<?php
$query
= "begin null; end;";
$stid = oci_parse($conn, "$query");
?>

or

<?php
$stid
= oci_parse($conn, "begin null; end;");
?>
up
1
michael dot virnstein at brodos dot de
17 years ago
A neat way to parse a query only once per script, if the query is done inside a function:

<?php
function querySomething($conn, $id)
{
static
$stmt;

if (
is_null($stmt)) {
$stmt = oci_parse($conn, 'select * from t where pk = :id');
}

oci_bind_by_name($stmt, ':id', $id, -1);

oci_execute($stmt, OCI_DEFAULT);

return
oci_fetch_array($stmt, OCI_ASSOC);

}

?>

With the static variable, the statment handle isn't closed after the function has terminated. Very nice for functions that are called e.g. in loops. Unfortunately this only works for static sql. If you have dynamic sql, you can do the following:

<?php

function querySomething($conn, $data)
{
static
$stmt = array();

$first = true;

$query = 'select * from t';

foreach (
$data as $key => $value) {
if (
$first) {
$first = false;
$query .= ' where ';
} else {
$query .= ' and ';
}

$query .= "$key = :b$key";
}

$queryhash = md5($query);

if (
is_null($stmt[$queryhash])) {
$stmt[$queryhash] = oci_parse($conn, $query);
}

foreach (
$data as $key => $value) {
// don't use $value, because we bind memory addresses here.
// this would result in every bind pointing at the same value after foreach
oci_bind_by_name($stmt[$queryhash], ":b$key", $data[$key], -1);
}

oci_execute($stmt[$queryhash], OCI_DEFAULT);

return
oci_fetch_array($stmt[$queryhash], OCI_ASSOC);

}

?>
up
0
kurt at kovac dot ch
20 years ago
For those that are having trouble with error checking, i have noticed on a lot of sites that people are trying to check the statement handle for error messages with OCIParse. Since the statement handle ($sth) is not created yet, you need to check the database handle ($dbh) for any errors with OCIParse. For example:

instead of:

<?php
$stmt
= OCIParse($conn, $query);
if (!
$stmt) {
$oerr = OCIError($stmt);
echo
"Fetch Code 1:".$oerr["message"];
exit;
}
?>

use:

<?php
$stmt
= OCIParse($conn, $query);
if (!
$stmt) {
$oerr = OCIError($conn);
echo
"Fetch Code 1:".$oerr["message"];
exit;
}
?>

Hope this helps someone.
up
-1
egypt at nmt dot edu
21 years ago
Whereas MySQL doesn't care what kind of quotes are around a LIKE clause, ociexecute gives the error:
ociexecute(): OCIStmtExecute: ORA-00904: "NM": invalid identifier
for the following.
<?php
$sql
= "SELECT * FROM addresses "
. "WHERE state LIKE \"NM\""; // error!
$stmt = ociparse($conn, $sql);
ociexecute($stmt);
?>

it's fine if you just use single quotes:
. "WHERE state LIKE 'NM'";
but i think it's interesting that ociparse doesn't say anything
up
-5
falundir at gmail dot com
13 years ago
When you want to call stored function (and want to read its result) which executes DML queries (insert, update, delete) inside its body you can't use "select your_stored_function(:param1, :param2) from dual" because you will receive "ORA-14551: cannot perform a DML operation inside a query" error.

In order to call such function and get its result you need to wrap it into nested procedure with OUT parameter like this:

DECLARE
PROCEDURE caller(return_value OUT NUMBER) AS
BEGIN
return_value := your_stored_function(:param1, :param2);
END;
BEGIN
caller(:return_value);
END;

and bind to :return_value variable to get the result of function.
To Top