OCI8 函数
在线手册:中文  英文

oci_parse

(PHP 5, PECL OCI8 >= 1.1.0)

oci_parse配置 Oracle 语句预备执行

说明

resource oci_parse ( resource $connection , string $query )

oci_parse()connection 上配置 query 并返回语句标识符以用于 oci_bind_by_name()oci_execute() 以及其它函数。

Note:

本函数并不验证 query。要知道 query 是否是合法的 SQL 或 PL/SQL 语句的唯一方法是执行它。

oci_parse() 在出错时返回 FALSE

Note:

在 PHP 5.0.0 之前的版本必须使用 ociparse() 替代本函数。该函数名仍然可用,为向下兼容作为 oci_parse() 的别名。不过其已被废弃,不推荐使用。


OCI8 函数
在线手册:中文  英文

用户评论:

falundir at gmail dot com (2011-02-08 05:38:19)

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.

michael dot virnstein at brodos dot de (2007-12-04 08:43:32)

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($stmtOCI_DEFAULT);

    return 
oci_fetch_array($stmtOCI_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);

}

?>

(2006-01-26 16:05:34)

one of the most things that is done wrong with oracle is the following.

Cosider:

<?php
$dbh 
ocilogon('user''pass''db');

for (
$i 0$i<=10$i++) {
    
$sth ociparse($dbh'SELECT * FROM T WHERE x = :x');

    
ocibindbyname($sth':x'$i, -1);
    
ociexecute($sthOCI_DEFAULT);
    if (
ocifetchrow($sth$rowOCI_ASSOC+OCI_RETURN_NULLS)) {
        
var_dump($row);
    }
}

ocilogoff($dbh);
?>

Problem here is, that you parse the same statement over and over and that'll cost ressources and will introduce many wait events. This problem will increase exponentially with the number of users using your system. That's one of the things besides not using bind variables that will prevent your application from scaling well.

The right approach:

<?php
$dbh 
ocilogon('user''pass''db');
$sth ociparse($dbh'SELECT * FROM T WHERE x = :x');
for (
$i 0$i<=10$i++) {
    
ocibindbyname($sth':x'$i, -1);
    
ociexecute($sthOCI_DEFAULT);
    if (
ocifetchrow($sth$rowOCI_ASSOC+OCI_RETURN_NULLS)) {
        
var_dump($row);
    }
}
ocilogoff($dbh);
?>

Now we are parsing the statement once and using it as often as possible. 

When your using Oracle, create proper indexes, use bind variables and parse once and execute often. Not doing so will get you into trouble when more than a few users are working with your application simultaneously.

kurt at kovac dot ch (2004-05-04 08:40:14)

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.

jicurito at hotmail dot com (2003-12-09 16:41:45)

regarding egypt note on double quotes, the reason for that behaviour is that Oracle treats things with double quotes as identifiers on a given statement... using single quotes won't provoque mistakes...

egypt at nmt dot edu (2003-10-14 19:31:48)

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

mwd at modulo3 dot de (2000-12-22 07:21:10)

if you're using "complex" statements e.g such having calls to build in oracle functions in the select list (as in example below), I did not find any other way as using the "AS <Name>" clause to being able to output the functions outcome using ociresult

example:

<?php
ociparse
($conn,"select EMPNO, LPAD(' ', 2*(LEVEL-1)) || ENAME AS COMPLETE_FANTASY_NAME, JOB, HIREDATE from scott.emp start with job='MANAGER' connect by PRIOR EMPNO = MGR");

echo 
ociresult $stmt,"COMPLETE_FANTASY_NAME")." ";
?>

BTW: I also found out by TAE that "COMPLETE_FANATASY_NAME" might not be "complete fantasy" as it has to be all capital letters.

易百教程