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;");
?>
(PHP 5, PHP 7, PHP 8, PECL OCI8 >= 1.1.0)
oci_parse — Prepara uma instrução Oracle para execução
Prepara sql
usando
connection
e retorna o identificador da instrução,
que pode ser usado com oci_bind_by_name(),
oci_execute() e outras funções.
Identificadores de instrução podem ser liberados
com oci_free_statement() ou definindo a
variável como null
.
connection
Um identificador de conexão Oracle, retornado por oci_connect(), oci_pconnect() ou oci_new_connect().
sql
A instrução SQL ou PL/SQL.
Instruções SQL não devem terminar com um ponto e vírgula (";"). Instruções PL/SQL devem terminar com um ponto e vírgula (";").
Retorna um identificador de instrução em caso de sucesso, ou false
em caso de erro.
Exemplo #1 Exemplo de oci_parse() para instruções SQL
<?php
$conn = oci_connect('hr', 'welcome', 'localhost/XE');
// Analisa a instrução. Observe que não há ponto e vírgula final na instrução 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) : " ") . "</td>\n";
}
echo "</tr>\n";
}
echo "</table>\n";
?>
Exemplo #2 Exemplo de oci_parse() para instruções PL/SQL
<?php
/*
Antes de executar o programa PHP, crie um procedimento armazenado no
SQL*Plus ou 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;
// Ao analisar programas PL/SQL, deve haver um ponto e vírgula final na string
$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"; // exibe 16
oci_free_statement($stid);
oci_close($conn);
?>
Nota:
This function does not validate
sql
. The only way to find out ifsql
is a valid SQL or PL/SQL statement is to execute it.
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;");
?>
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);
}
?>
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.
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
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.