如果要将 PL/SQL 用于变量
<?php
$query = "begin null; end;";
$stid = oci_parse($conn, "$query");
?>
或者
<?php
$stid = oci_parse($conn, "begin null; end;");
?>
(PHP 5, PHP 7, PHP 8, PECL OCI8 >= 1.1.0)
oci_parse — 准备 Oracle 语句以供执行
使用 connection
准备 sql
并返回语句标识符,该标识符可与 oci_bind_by_name()、oci_execute() 和其他函数一起使用。
可以使用 oci_free_statement() 或将变量设置为 null
来释放语句标识符。
connection
一个 Oracle 连接标识符,由 oci_connect()、oci_pconnect() 或 oci_new_connect() 返回。
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) : " ") . "</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 语句的唯一方法是执行它。
如果要将 PL/SQL 用于变量
<?php
$query = "begin null; end;";
$stid = oci_parse($conn, "$query");
?>
或者
<?php
$stid = oci_parse($conn, "begin null; end;");
?>
如果查询在函数内完成,则以简洁的方式仅对每个脚本解析一次查询
<?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);
}
?>
使用静态变量后,语句句柄在函数终止后不会关闭。对于例如在循环中调用的函数来说非常方便。不幸的是,这只适用于静态SQL。如果使用动态SQL,可以执行以下操作
<?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) {
// 不要使用 $value,因为我们在这里绑定内存地址。
// 这将导致在 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);
}
?>
对于那些在错误检查方面遇到麻烦的人,我注意到许多网站上的人都试图使用 OCIParse 检查语句句柄的错误消息。由于语句句柄($sth)尚未创建,因此需要使用 OCIParse 检查数据库句柄($dbh)是否存在任何错误。例如
不要使用
<?php
$stmt = OCIParse($conn, $query);
if (!$stmt) {
$oerr = OCIError($stmt);
echo "Fetch Code 1:".$oerr["message"];
exit;
}
?>
请使用
<?php
$stmt = OCIParse($conn, $query);
if (!$stmt) {
$oerr = OCIError($conn);
echo "Fetch Code 1:".$oerr["message"];
exit;
}
?>
希望这对某些人有所帮助。
虽然 MySQL 不关心 LIKE 子句周围使用哪种引号,但 ociexecute 会给出以下错误:
ociexecute(): OCIStmtExecute: ORA-00904: "NM": invalid identifier
对于以下代码:
<?php
$sql = "SELECT * FROM addresses "
. "WHERE state LIKE \"NM\""; // 错误!
$stmt = ociparse($conn, $sql);
ociexecute($stmt);
?>
如果只使用单引号,则一切正常
". "WHERE state LIKE 'NM'";
但我认为 ociparse 没有报错这一点很有趣
当要调用存储函数(并读取其结果)且其主体中执行 DML 查询(插入、更新、删除)时,不能使用“select your_stored_function(:param1, :param2) from dual”,因为将收到“ORA-14551: cannot perform a DML operation inside a query”错误。
为了调用此类函数并获取其结果,需要将其包装到具有 OUT 参数的嵌套过程中,如下所示:
DECLARE
PROCEDURE caller(return_value OUT NUMBER) AS
BEGIN
return_value := your_stored_function(:param1, :param2);
END;
BEGIN
caller(:return_value);
END;
并将绑定到 :return_value 变量以获取函数的结果。