C. Oracle Functions

Introduction

These functions allow you to access Oracle 10, Oracle 9, Oracle 8 and Oracle 7 databases using the Oracle Call Interface (OCI). They support binding of PHP variables to Oracle placeholders, have full LOB, FILE and ROWID support, and allow you to use user-supplied define variables.

Requirements

You will need the Oracle client libraries to use this extension. Windows users will need libraries with version at least 10 to use the php_oci8.dll.

The most convenient way to install all the required files is to use Oracle Instant Client, which is available from here: http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html. To work with OCI8 module "basic" version of Oracle Instant Client is enough. Instant Client does not need ORACLE_SID or ORACLE_HOME environment variables set. You still may need to set LD_LIBRARY_PATH and NLS_LANG, though.

Before using this extension, make sure that you have set up your Oracle environment variables properly for the Oracle user, as well as your web daemon user. These variables should be set up before you start your web-server. The variables you might need to set are as follows:

  • ORACLE_HOME

  • ORACLE_SID

  • LD_PRELOAD

  • LD_LIBRARY_PATH

  • NLS_LANG

For less frequently used Oracle environment variables such as TNS_ADMIN, TWO_TASK, ORA_TZFILE, and the various Oracle globalization settings like ORA_NLS33, ORA_NLS10 and the NLS_* variables refer to Oracle documentation.

After setting up the environment variables for your webserver user, be sure to also add the webserver user (nobody, www) to the oracle group.

If your webserver doesn't start or crashes at startup: Check that Apache is linked with the pthread library:

# ldd /www/apache/bin/httpd
    libpthread.so.0 => /lib/libpthread.so.0 (0x4001c000)
    libm.so.6 => /lib/libm.so.6 (0x4002f000)
    libcrypt.so.1 => /lib/libcrypt.so.1 (0x4004c000)
    libdl.so.2 => /lib/libdl.so.2 (0x4007a000)
    libc.so.6 => /lib/libc.so.6 (0x4007e000)
    /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

If the libpthread is not listed you have to reinstall Apache:

# cd /usr/src/apache_1.3.xx
# make clean
# LIBS=-lpthread ./config.status
# make
# make install

Please note that on some systems, like UnixWare it is libthread instead of libpthread. PHP and Apache have to be configured with EXTRA_LIBS=-lthread.

Runtime Configuration

The behaviour of these functions is affected by settings in php.ini.

Table 1. OCI8 Configuration Options

NameDefaultChangeableChangelog
oci8.privileged_connect"0"PHP_INI_SYSTEMAvailable since PHP 5.1.2.
oci8.max_persistent"-1"PHP_INI_SYSTEMAvailable since PHP 5.1.2.
oci8.persistent_timeout"-1"PHP_INI_SYSTEMAvailable since PHP 5.1.2.
oci8.ping_interval"60"PHP_INI_SYSTEMAvailable since PHP 5.1.2.
oci8.statement_cache_size"20"PHP_INI_SYSTEMAvailable since PHP 5.1.2.
oci8.default_prefetch"10"PHP_INI_SYSTEMAvailable since PHP 5.1.2.
oci8.old_oci_close_semantics"0"PHP_INI_SYSTEMAvailable since PHP 5.1.2.

Here's a short explanation of the configuration directives.

oci8.privileged_connect boolean

This option enables privileged connections using external credentials (OCI_SYSOPER, OCI_SYSDBA).

oci8.max_persistent int

The maximum number of persistent OCI8 connections per process. Setting this option to -1 means that there is no limit.

oci8.persistent_timeout int

The maximum length of time (in seconds) that a given process is allowed to maintain an idle persistent connection. Setting this option to -1 means that idle persistent connections will be maintained forever.

oci8.ping_interval int

The length of time (in seconds) that must pass before issuing a ping during oci_pconnect(). When set to 0, persistent connections will be pinged every time they are reused. To disable pings completely, set this option to -1.

Note: Disabling pings will cause oci_pconnect() calls to operate at the highest efficiency, but may cause PHP to not detect faulty connections, such as those caused by network partitions, or if the Oracle server has gone down since PHP connected, until later in the script. Consult the oci_pconnect() documentation for more information.

oci8.statement_cache_size int

This option enables statement caching, and specifies how many statements to cache. To disable statement caching just set this option to 0.

Note: A larger cache can result in improved performance, at the cost of increased memory usage.

oci8.default_prefetch int

This option enables statement prefetching and sets the default number of rows that will be fetched automatically after statement execution.

Note: A larger prefetch can result in improved performance, at the cost of increased memory usage.

oci8.old_oci_close_semantics boolean

This option controls oci_close() behaviour. Enabling it means that oci_close() will do nothing; the connection will not be closed until the end of the script. This is for backward compatibility only. If you find that you need to enable this setting, you are strongly encouraged to remove the oci_close() calls from your application instead of enabling this option.

Predefined Constants

The constants below are defined by this extension, and will only be available when the extension has either been compiled into PHP or dynamically loaded at runtime.

OCI_DEFAULT (integer)

Statement execution mode. Statement is not committed automatically when using this mode.

OCI_DESCRIBE_ONLY (integer)

Statement execution mode. Use this mode if you don't want to execute the query, but get the select-list's description.

OCI_COMMIT_ON_SUCCESS (integer)

Statement execution mode. Statement is automatically committed after oci_execute() call.

OCI_EXACT_FETCH (integer)

Statement fetch mode. Used when the application knows in advance exactly how many rows it will be fetching. This mode turns prefetching off for Oracle release 8 or later mode. Cursor is cancelled after the desired rows are fetched and may result in reduced server-side resource usage.

OCI_SYSDATE (integer)

OCI_B_BFILE (integer)

Used with oci_bind_by_name() when binding BFILEs.

OCI_B_CFILEE (integer)

Used with oci_bind_by_name() when binding CFILEs.

OCI_B_CLOB (integer)

Used with oci_bind_by_name() when binding CLOBs.

OCI_B_BLOB (integer)

Used with oci_bind_by_name() when binding BLOBs.

OCI_B_ROWID (integer)

Used with oci_bind_by_name() when binding ROWIDs.

OCI_B_CURSOR (integer)

Used with oci_bind_by_name() when binding cursors, previously allocated with oci_new_descriptor().

OCI_B_NTY (integer)

Used with oci_bind_by_name() when binding named data types. Note: in PHP < 5.0 it was called OCI_B_SQLT_NTY.

OCI_B_BIN (integer)

SQLT_BFILEE (integer)

The same as OCI_B_BFILE.

SQLT_CFILEE (integer)

The same as OCI_B_CFILEE.

SQLT_CLOB (integer)

The same as OCI_B_CLOB.

SQLT_BLOB (integer)

The same as OCI_B_BLOB.

SQLT_RDD (integer)

The same as OCI_B_ROWID.

SQLT_NTY (integer)

The same as OCI_B_NTY.

SQLT_NUM (integer)

Used with oci_bind_array_by_name() to bind arrays of NUMBER.

SQLT_INT (integer)

Used with oci_bind_array_by_name() to bind arrays of INTEGER.

SQLT_AFC (integer)

Used with oci_bind_array_by_name() to bind arrays of CHAR.

SQLT_CHR (integer)

Used with oci_bind_array_by_name() to bind arrays of VARCHAR2.

SQLT_VCS (integer)

Used with oci_bind_array_by_name() to bind arrays of VARCHAR.

SQLT_AVC (integer)

Used with oci_bind_array_by_name() to bind arrays of CHARZ.

SQLT_STR (integer)

Used with oci_bind_array_by_name() to bind arrays of STRING.

SQLT_LVC (integer)

Used with oci_bind_array_by_name() to bind arrays of LONG VARCHAR.

SQLT_FLT (integer)

Used with oci_bind_array_by_name() to bind arrays of FLOAT.

SQLT_LNG (integer)

SQLT_ODT (integer)

Used with oci_bind_array_by_name() to bind arrays of LONG.

SQLT_BDOUBLE (integer)

SQLT_BFLOAT (integer)

OCI_FETCHSTATEMENT_BY_COLUMN (integer)

Default mode of oci_fetch_all().

OCI_FETCHSTATEMENT_BY_ROW (integer)

Alternative mode of oci_fetch_all().

OCI_ASSOC (integer)

Used with oci_fetch_all() and oci_fetch_array() to get an associative array as a result.

OCI_NUM (integer)

Used with oci_fetch_all() and oci_fetch_array() to get an enumerated array as a result.

OCI_BOTH (integer)

Used with oci_fetch_all() and oci_fetch_array() to get an array with both associative and number indices.

OCI_RETURN_NULLS (integer)

Used with oci_fetch_array() to get empty array elements if field's value is NULL.

OCI_RETURN_LOBS (integer)

Used with oci_fetch_array() to get value of LOB instead of the descriptor.

OCI_DTYPE_FILE (integer)

This flag tells oci_new_descriptor() to initialize new FILE descriptor.

OCI_DTYPE_LOB (integer)

This flag tells oci_new_descriptor() to initialize new LOB descriptor.

OCI_DTYPE_ROWID (integer)

This flag tells oci_new_descriptor() to initialize new ROWID descriptor.

OCI_D_FILE (integer)

The same as OCI_DTYPE_FILE.

OCI_D_LOB (integer)

The same as OCI_DTYPE_LOB.

OCI_D_ROWID (integer)

The same as OCI_DTYPE_ROWID.

OCI_SYSOPER (integer)

Used with oci_connect() to connect as SYSOPER using external credentials (oci8.privileged_connect should be enabled for this).

OCI_SYSDBA (integer)

Used with oci_connect() to connect as SYSDBA using external credentials (oci8.privileged_connect should be enabled for this).

OCI_LOB_BUFFER_FREE (integer)

Used with OCI-Lob->flush to free buffers used.

OCI_TEMP_CLOB (integer)

Used with OCI-Lob->writeTemporary to indicate explicilty that temporary CLOB should be created.

OCI_TEMP_BLOB (integer)

Used with OCI-Lob->writeTemporary to indicate explicilty that temporary BLOB should be created.

Examples

Example 1. Basic query

<?php

  $conn
= oci_connect('hr', 'hr', 'orcl');
  if (!
$conn) {
    
$e = oci_error();
    print
htmlentities($e['message']);
    exit;
  }

  
$query = 'SELECT * FROM DEPARTMENTS';

  
$stid = oci_parse($conn, $query);
  if (!
$stid) {
    
$e = oci_error($conn);
    print
htmlentities($e['message']);
    exit;
  }

  
$r = oci_execute($stid, OCI_DEFAULT);
  if (!
$r) {
    
$e = oci_error($stid);
    echo
htmlentities($e['message']);
    exit;
  }

  print
'<table border="1">';
  while (
$row = oci_fetch_array($stid, OCI_RETURN_NULLS)) {
    print
'<tr>';
       foreach (
$row as $item) {
         print
'<td>'.($item?htmlentities($item):'&nbsp;').'</td>';
       }
       print
'</tr>';
  }
  print
'</table>';

  
oci_close($conn);
?>

Example 2. Insert with bind variables

<?php

  
// Before running, create the table:
  //   CREATE TABLE MYTABLE (mid NUMBER, myd VARCHAR2(20));

  
$conn = oci_connect('scott', 'tiger', 'orcl');

  
$query = 'INSERT INTO MYTABLE VALUES(:myid, :mydata)';

  
$stid = oci_parse($conn, $query);

  
$id = 60;
  
$data = 'Some data';

  
oci_bind_by_name($stid, ':myid', $id);
  
oci_bind_by_name($stid, ':mydata', $data);

  
$r = oci_execute($stid);

  if (
$r)
    print
"One row inserted";

  
oci_close($conn);

?>

Example 3. Inserting data into a CLOB column

<?php

// Before running, create the table:
//     CREATE TABLE MYTABLE (mykey NUMBER, myclob CLOB);

$conn = oci_connect('scott', 'tiger', 'orcl');

$mykey = 12343;  // arbitrary key for this example;

$sql = "INSERT INTO mytable (mykey, myclob)
        VALUES (:mykey, EMPTY_CLOB())
        RETURNING myclob INTO :myclob"
;

$stid = oci_parse($conn, $sql);
$clob = oci_new_descriptor($conn, OCI_D_LOB);
oci_bind_by_name($stid, ":mykey", $mykey, 5);
oci_bind_by_name($stid, ":myclob", $clob, -1, OCI_B_CLOB);
oci_execute($stid, OCI_DEFAULT);
$clob->save("A very long string");

oci_commit($conn);

// Fetching CLOB data

$query = 'SELECT myclob FROM mytable WHERE mykey = :mykey';

$stid = oci_parse ($conn, $query);
oci_bind_by_name($stid, ":mykey", $mykey, 5);
oci_execute($stid, OCI_DEFAULT);

print
'<table border="1">';
while (
$row = oci_fetch_array($stid, OCI_ASSOC)) {
  
$result = $row['MYCLOB']->load();
  print
'<tr><td>'.$result.'</td></tr>';
}
print
'</table>';

?>

You can easily access stored procedures in the same way as you would from the command line.

Example 4. Using Stored Procedures

<?php
// by webmaster at remoterealty dot com
$sth = oci_parse($dbh, "begin sp_newaddress( :address_id, '$firstname',
'$lastname', '$company', '$address1', '$address2', '$city', '$state',
'$postalcode', '$country', :error_code );end;"
);

// This calls stored procedure sp_newaddress, with :address_id being an
// in/out variable and :error_code being an out variable.
// Then you do the binding:

   
oci_bind_by_name($sth, ":address_id", $addr_id, 10);
   
oci_bind_by_name($sth, ":error_code", $errorcode, 10);
   
oci_execute($sth);

?>

Connecting Handling

The oci8 extension provides you with 3 different functions for connecting to Oracle. It is up to you to use the most appropriate function for your application, and the information in this section is intended to help you make an informed choice.

Connecting to an Oracle server is a reasonably expensive operation, in terms of the time that it takes to complete. The oci_pconnect() function uses a persistent cache of connections that can be re-used across different script requests. This means that you will typically only incur the connection overhead once per php process (or apache child).

If your application connects to Oracle using a different set of credentials for each web user, the persistent cache employed by oci_pconnect() will become less useful as the number of concurrent users increases, to the point where it may start to adversely affect the overall performance of your Oracle server due to maintaining too many idle connections. If your application is structured in this way, it is recommended that you either tune your application using the oci8.max_persistent and oci8.persistent_timeout configuration settings (these will give you control over the persistent connection cache size and lifetime) or use oci_connect() instead.

Both oci_connect() and oci_pconnect() employ a connection cache; if you make multiple calls to oci_connect(), using the same parameters, in a given script, the second and subsequent calls return the existing connection handle. The cache used by oci_connect() is cleaned up at the end of the script run, or when you explicitly close the connection handle. oci_pconnect() has similar behaviour, although its cache is maintained separately and survives between requests.

This caching feature is important to remember, because it gives the appearance that the two handles are not transactionally isolated (they are in fact the same connection handle, so there is no isolation of any kind). If your application needs two separate, transactionally isolated connections, you should use oci_new_connect().

oci_new_connect() always creates a new connection to the Oracle server, regardless of what other connections might already exist. High traffic web applications should try to avoid using oci_new_connect(), especially in the busiest sections of the application.

Datatypes supported by the driver

Table 2. The driver supports the following types when binding parameters using oci_bind_by_name() function:

TypeMapping
SQLT_NTYMaps a native collection type from a PHP collection object, such as those created by oci_new_collection().
SQLT_BFILEEMaps a native descriptor, such as those created by oci_new_descriptor().
SQLT_CFILEEMaps a native descriptor, such as those created by oci_new_descriptor().
SQLT_CLOBMaps a native descriptor, such as those created by oci_new_descriptor().
SQLT_BLOBMaps a native descriptor, such as those created by oci_new_descriptor().
SQLT_RDDMaps a native descriptor, such as those created by oci_new_descriptor().
SQLT_NUMConverts the PHP parameter to a 'C' long type, and binds to that value.
SQLT_RSETMaps a native statement handle, such as those created by oci_parse() or those retrieved from other OCI queries.
SQLT_CHR and any other typeConverts the PHP parameter to a string type and binds as a string.

Table 3. The following types are supported when retrieving columns from a result set:

TypeMapping
SQLT_RSETCreates an oci statement resource to represent the the cursor.
SQLT_RDDCreates a ROWID object.
SQLT_BLOBCreates a LOB object.
SQLT_CLOBCreates a LOB object.
SQLT_BFILECreates a LOB object.
SQLT_LNGBound as SQLT_CHR, returned as a string
SQLT_LBIBound as SQLT_BIN, returned as a string
Any other typeBound as SQLT_CHR, returned as a string
Table of Contents
OCI-Collection->append -- Appends element to the collection
OCI-Collection->assign -- Assigns a value to the collection from another existing collection
OCI-Collection->assignElem -- Assigns a value to the element of the collection
OCI-Collection->free -- Frees the resources associated with the collection object
OCI-Collection->getElem -- Returns value of the element
OCI-Collection->max -- Returns the maximum number of elements in the collection
OCI-Collection->size -- Returns size of the collection
OCI-Collection->trim -- Trims elements from the end of the collection
OCI-Lob->append -- Appends data from the large object to another large object
OCI-Lob->close -- Closes LOB descriptor
OCI-Lob->eof -- Tests for end-of-file on a large object's descriptor
OCI-Lob->erase -- Erases a specified portion of the internal LOB data
OCI-Lob->export -- Exports LOB's contents to a file
OCI-Lob->flush -- Flushes/writes buffer of the LOB to the server
OCI-Lob->free -- Frees resources associated with the LOB descriptor
OCI-Lob->getBuffering -- Returns current state of buffering for the large object
OCI-Lob->import -- Imports file data to the LOB
OCI-Lob->load -- Returns large object's contents
OCI-Lob->read -- Reads part of the large object
OCI-Lob->rewind -- Moves the internal pointer to the beginning of the large object
OCI-Lob->save -- Saves data to the large object
OCI-Lob->saveFile -- Alias of oci_lob_import()
OCI-Lob->seek -- Sets the internal pointer of the large object
OCI-Lob->setBuffering -- Changes current state of buffering for the large object
OCI-Lob->size -- Returns size of large object
OCI-Lob->tell -- Returns current position of internal pointer of large object
OCI-Lob->truncate -- Truncates large object
OCI-Lob->write -- Writes data to the large object
OCI-Lob->writeTemporary -- Writes temporary large object
OCI-Lob->writeToFile -- Alias of oci_lob_export()
oci_bind_array_by_name --  Binds PHP array to Oracle PL/SQL array by name
oci_bind_by_name --  Binds the PHP variable to the Oracle placeholder
oci_cancel -- Cancels reading from cursor
oci_close -- Closes Oracle connection
oci_commit -- Commits outstanding statements
oci_connect -- Establishes a connection to the Oracle server
oci_define_by_name --  Uses a PHP variable for the define-step during a SELECT
oci_error -- Returns the last error found
oci_execute -- Executes a statement
oci_fetch_all -- Fetches all rows of result data into an array
oci_fetch_array -- Returns the next row from the result data as an associative or numeric array, or both
oci_fetch_assoc -- Returns the next row from the result data as an associative array
oci_fetch_object -- Returns the next row from the result data as an object
oci_fetch_row -- Returns the next row from the result data as a numeric array
oci_fetch -- Fetches the next row into result-buffer
oci_field_is_null -- Checks if the field is NULL
oci_field_name -- Returns the name of a field from the statement
oci_field_precision -- Tell the precision of a field
oci_field_scale -- Tell the scale of the field
oci_field_size -- Returns field's size
oci_field_type_raw -- Tell the raw Oracle data type of the field
oci_field_type -- Returns field's data type
oci_free_statement --  Frees all resources associated with statement or cursor
oci_internal_debug -- Enables or disables internal debug output
oci_lob_copy -- Copies large object
oci_lob_is_equal -- Compares two LOB/FILE locators for equality
oci_new_collection -- Allocates new collection object
oci_new_connect -- Establishes a new connection to the Oracle server
oci_new_cursor -- Allocates and returns a new cursor (statement handle)
oci_new_descriptor -- Initializes a new empty LOB or FILE descriptor
oci_num_fields --  Returns the number of result columns in a statement
oci_num_rows -- Returns number of rows affected during statement execution
oci_parse -- Prepares Oracle statement for execution
oci_password_change -- Changes password of Oracle's user
oci_pconnect -- Connect to an Oracle database using a persistent connection
oci_result -- Returns field's value from the fetched row
oci_rollback -- Rolls back outstanding transaction
oci_server_version -- Returns server version
oci_set_prefetch -- Sets number of rows to be prefetched
oci_statement_type -- Returns the type of an OCI statement
ocibindbyname -- Alias of oci_bind_by_name()
ocicancel -- Alias of oci_cancel()
ocicloselob -- Alias of OCI-Lob->close
ocicollappend -- Alias of OCI-Collection->append
ocicollassign -- Alias of OCI-Collection->assign
ocicollassignelem -- Alias of OCI-Collection->assignElem
ocicollgetelem -- Alias of OCI-Collection->getElem
ocicollmax -- Alias of OCI-Collection->max
ocicollsize -- Alias of OCI-Collection->size
ocicolltrim -- Alias of OCI-Collection->trim
ocicolumnisnull -- Alias of oci_field_is_null()
ocicolumnname -- Alias of oci_field_name()
ocicolumnprecision -- Alias of oci_field_precision()
ocicolumnscale -- Alias of oci_field_scale()
ocicolumnsize -- Alias of oci_field_size()
ocicolumntype -- Alias of oci_field_type()
ocicolumntyperaw -- Alias of oci_field_type_raw()
ocicommit -- Alias of oci_commit()
ocidefinebyname -- Alias of oci_define_by_name()
ocierror -- Alias of oci_error()
ociexecute -- Alias of oci_execute()
ocifetch -- Alias of oci_fetch()
ocifetchinto -- Fetches the next row into an array
ocifetchstatement -- Alias of oci_fetch_all()
ocifreecollection -- Alias of OCI-Collection->free
ocifreecursor -- Alias of oci_free_statement()
ocifreedesc -- Alias of OCI-Lob->free
ocifreestatement -- Alias of oci_free_statement()
ociinternaldebug -- Alias of oci_internal_debug()
ociloadlob -- Alias of OCI-Lob->load
ocilogoff -- Alias of oci_close()
ocilogon -- Alias of oci_connect()
ocinewcollection -- Alias of oci_new_collection()
ocinewcursor -- Alias of oci_new_cursor()
ocinewdescriptor -- Alias of oci_new_descriptor()
ocinlogon -- Alias of oci_new_connect()
ocinumcols -- Alias of oci_num_fields()
ociparse -- Alias of oci_parse()
ociplogon -- Alias of oci_pconnect()
ociresult -- Alias of oci_result()
ocirollback -- Alias of oci_rollback()
ocirowcount -- Alias of oci_num_rows()
ocisavelob -- Alias of OCI-Lob->save
ocisavelobfile -- Alias of OCI-Lob->import
ociserverversion -- Alias of oci_server_version()
ocisetprefetch -- Alias of oci_set_prefetch()
ocistatementtype -- Alias of oci_statement_type()
ociwritelobtofile -- Alias of OCI-Lob->export
ociwritetemporarylob -- Alias of OCI-Lob->writeTemporary