PHP Australia Conference 2015

oci_bind_by_name

(PHP 5, PECL OCI8 >= 1.1.0)

oci_bind_by_nameVincula una variable de PHP a un parámetro de sustitución de Oracle

Descripción

bool oci_bind_by_name ( resource $statement , string $bv_name , mixed &$variable [, int $maxlength = -1 [, int $type = SQLT_CHR ]] )

Vincula la variable de PHP variable al parámetro de sustitución de variable vinculada de Oracle bv_name. La vinculación es importante para el rendimiento de la base de datos de Oracle y también como un forma de evitar problemas de seguridad de Inyecciones SQL.

La vinculación permite que la base de datos reutilice el contexto de la sentencia y use la caché desde ejecuciones previas de dicha sentencia, incluso si otro usuario o proceso la ejecutó inicialmente. La vinculación reduce las inquietudes con Inyecciones SQL ya que los datos asociados con una variable vinculada nunca son tratados como parte de la sentencia SQL. Hace que no sean necesarios la entrecomillación o el escape.

Las variables de PHP que han sido vinculadas se pueden cambiar, por lo que la sentencia se reejecutará sin necesidad de reanalizarla o revincularla.

En Oracle, la vinculaión de variables se divide normalmente en vínculos IN para valores que son pasados a la base de datos, y vínculos OUT para valores que son devueltos a PHP. Una variable vinculada podría ser tanto IN como OUT. Si una variable vinculada será usada para entrada o salida se determina en en tiempo de ejecución.

Se debe especificar maxlength al utilizar un vínculo OUT para que PHP asigne suficiente memoria para contener el valor devuelto.

Para los vínculos IN, se recomienda establecer la longitud maxlength si la sentencia es reejecutada múltiples veces con diferentes valores para la variable de PHP. Si no, Oracle podría truncar los datos a la longitud del valor inicial de la variable de PHP. Si no se conoce cuál será la longitud máxima, reinvoque a oci_bind_by_name() con el tamaño de los datos actuales antes de cada llamada a oci_execute(). Vincular una longitud grande innecesariamente tendrá un impacto en la memoria del proceso de la base de datos.

Una llamada vinculada le indica a Oracle desde qué dirección de memoria debe leer datos. Para vínculos IN, esta dirección necesita contener datos válidos cuando se invoque a oci_execute(). Esto significa que la variable vinculada debe permanecer en el ámbito hasta su ejecución. Si no se hace, pueden ocurrir errores inesperados como "ORA-01460: unimplemented or unreasonable conversion requested". Para vínculos OUT, un síntoma es que no se ha establecido un valor en la variable de PHP.

Para una sentencia que sea ejecutada repetidamente, los valores vinculados que nunca cambian podrían reducir la capacidad del optimizador de Oracle para elegir el mejor plan de ejecución de sentencias. Las sentencias que tarden en ejecutarse y que sean reejecutadas raramente podrían no beneficiarse de la vinculación. Sin embargo, en ambos casos, la vinculación podría ser más segura que unir cadenas en una sentencia SQL, ya que esto puede ser un riesgo para la seguridad si se concatena el texto no filtrado de un usuario.

Parámetros

statement

Un identificador de sentencia de OCI8 válido.

bv_name

El parámetro de sustitución de la variable vinculada prefijado por dos puntos (:) usado en la sentencia. Los dos puntos son opcionales en bv_name. Oracle no usa los signos de interrogación en los parámetros de sustitución.

variable

La variable de PHP que va a ser asociada con bv_name

maxlength

Establece la longitud máxima para los datos. Si se establece a -1, esta función utilizará la longitud actual de variable para establecer la longitud máxima. En este caso, el parámetro variable debe existir y contener datos cuando se invoque a oci_bind_by_name().

type

El tipo de datos con el que Oracle trartará los datos. El tipo usado predeterminado dado por type es SQLT_CHR. Oracle convertirá los datos entre este tipo y la columna de la base de datos (o un tipo de variable de PL/SQL), cuando sea posible.

Si fuera necesario vincular un tipo de datos abstractos (LOB/ROWID/BFILE), debe asignarlo primero usando la función oci_new_descriptor(). La longitud length no se usa para tipos de datos abstractos, por lo que debería establecerse a -1.

Los valores posibles para type son:

  • SQLT_BFILEE or OCI_B_BFILE - para BFILEs;

  • SQLT_CFILEE o OCI_B_CFILEE - para CFILEs;

  • SQLT_CLOB o OCI_B_CLOB - para CLOBs;

  • SQLT_BLOB o OCI_B_BLOB - para BLOBs;

  • SQLT_RDD o OCI_B_ROWID - para ROWIDs;

  • SQLT_NTY o OCI_B_NTY - para tipos de datos con nombre;

  • SQLT_INT o OCI_B_INT - para enteros;

  • SQLT_CHR - para VARCHARs;

  • SQLT_BIN o OCI_B_BIN - para columnas RAW;

  • SQLT_LNG - para columnas LONG;

  • SQLT_LBI - para columnas LONG RAW;

  • SQLT_RSET - para cursores creados con oci_new_cursor();

  • SQLT_BOL o OCI_B_BOL - para BOOLEAN de PL/SQL (Requiere OCI8 2.0.7 y Oracle Database 12c)

Valores devueltos

Devuelve TRUE en caso de éxito o FALSE en caso de error.

Ejemplos

Ejemplo #1 Insertar datos con oci_bind_by_name()

<?php

// Cree la tabla con:
//   CREATE TABLE mytab (id NUMBER, text VARCHAR2(40));

$conexión oci_connect('hr''welcome''localhost/XE');
if (!
$conexión) {
    
$m oci_error();
    
trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$stid oci_parse($conexión,"INSERT INTO mytab (id, text) VALUES(:id_bv, :text_bv)");

$id 1;
$texto "Datos a insertar     ";
oci_bind_by_name($stid":id_bv"$id);
oci_bind_by_name($stid":text_bv"$texto);
oci_execute($stid);

// La tabla ahora contiene: 1, 'Datos a insertar     '

?>

Ejemplo #2 Vincular una vez para múltiples ejecuciones

<?php

// Cree la tabla con:
//   CREATE TABLE mytab (id NUMBER);

$conexión oci_connect('hr''welcome''localhost/XE');
if (!
$conexión) {
    
$m oci_error();
    
trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$a = array(1,3,5,7,11);  // datos a insertar

$stid oci_parse($conexión'INSERT INTO mytab (id) VALUES (:bv)');
oci_bind_by_name($stid':bv'$v20);
foreach (
$a as $v) {
    
$r oci_execute($stidOCI_DEFAULT);  // no autoconsigna
}
oci_commit($conexión); // consigna todo una vez

// La tabla contiene cinco filas: 1, 3, 5, 7, 11

oci_free_statement($stid);
oci_close($conexión);

?>

Ejemplo #3 Vinculación con un bucle foreach()

<?php

$conexión 
oci_connect('hr''welcome''localhost/XE');
if (!
$conexión) {
    
$m oci_error();
    
trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$sql 'SELECT * FROM departments WHERE department_name = :dname AND location_id = :loc';
$stid oci_parse($conexión$sql);

$ba = array(':dname' => 'IT Support'':loc' => 1700);

foreach (
$ba as $clave => $valor) {

    
// oci_bind_by_name($stid, $clave, $valor) no funciona debido a
    // que vincula cada parámetro de sustitución a la misma ubicación: $valor
    // En su lugar, use la ubicación real de los datos: $ba[$clave]
    
oci_bind_by_name($stid$clave$ba[$clave]);
}

oci_execute($stid);
$fila oci_fetch_array($stidOCI_ASSOC+OCI_RETURN_NULLS);
foreach (
$fila as $item) {
    print 
$item."<br>\n";
}

oci_free_statement($stid);
oci_close($conexión);

?>

Ejemplo #4 Vinculación en una cláusula WHERE

<?php

$conexión 
oci_connect("hr""hrpwd""localhost/XE");
if (!
$conexión) {
    
$m oci_error();
    
trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$sql 'SELECT last_name FROM employees WHERE department_id = :didbv ORDER BY last_name';
$stid oci_parse($conexión$sql);
$didbv 60;
oci_bind_by_name($stid':didbv'$didbv);
oci_execute($stid);
while ((
$row oci_fetch_array($stidOCI_ASSOC)) != false) {
    echo 
$row['LAST_NAME'] ."<br>\n";
}

// La salida es
//    Austin
//    Ernst
//    Hunold
//    Lorentz
//    Pataballa

oci_free_statement($stid);
oci_close($conexión);

?>

Ejemplo #5 Vinculación con una cláusula LIKE

<?php

$conexión 
oci_connect('hr''welcome''localhost/XE');
if (!
$conexión) {
    
$m oci_error();
    
trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

// Busca todas las ciudades que empiecen por 'South'
$stid oci_parse($conexión"SELECT city FROM locations WHERE city LIKE :bv");
$ciudad 'South%';  // '%' es un comodín en SQL
oci_bind_by_name($stid":bv"$ciudad);
oci_execute($stid);
oci_fetch_all($stid$res);

foreach (
$res['CITY'] as $c) {
    print 
$c "<br>\n";
}
// La salida es
//   South Brunswick
//   South San Francisco
//   Southlake

oci_free_statement($stid);
oci_close($conexión);

?>

Ejemplo #6 Vinculación con REGEXP_LIKE

<?php

$conexión 
oci_connect('hr''welcome''localhost/XE');
if (!
$conexión) {
    
$m oci_error();
    
trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

// Busca todas las ciudades que contengan 'ing'
$stid oci_parse($conexión"SELECT city FROM locations WHERE REGEXP_LIKE(city, :bv)");
$ciudad '.*ing.*';
oci_bind_by_name($stid":bv"$ciudad);
oci_execute($stid);
oci_fetch_all($stid$res);

foreach (
$res['CITY'] as $c) {
    print 
$c "<br>\n";
}
// La salida es
//   Beijing
//   Singapore

oci_free_statement($stid);
oci_close($conexión);

?>

Para un número fijo pequeño de condiciones de la cláusula IN, use variables vinculadas individuales. Los valores desconocidos en tiempo de ejecución pueden ser establecidos a NULL. Esto permite que una única sentencia sea usada por todos los usuarios de una aplicación, maximizando la enficiencia de la caché de la base de datos de Oracle.

Ejemplo #7 Vinculación de múltiples valores en una cláusula IN

<?php

$conexión 
oci_connect('hr''welcome''localhost/XE');
if (!
$conexión) {
    
$m oci_error();
    
trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$sql 'SELECT last_name FROM employees WHERE employee_id in (:e1, :e2, :e3)';
$stid oci_parse($conexión$sql);
$mye1 103;
$mye2 104;
$mye3 NULL// se pretende que no se proporcione este valor
oci_bind_by_name($stid':e1'$mye1);
oci_bind_by_name($stid':e2'$mye2);
oci_bind_by_name($stid':e3'$mye3);
oci_execute($stid);
oci_fetch_all($stid$res);
foreach (
$res['LAST_NAME'] as $nombre) {
    print 
$nombre ."<br>\n";
}

// La salida es
//   Ernst
//   Hunold

oci_free_statement($stid);
oci_close($conexión);

?>

Ejemplo #8 Vinculación de un ROWID devuelto por una consulta

<?php

// Cree la tabla con:
//   CREATE TABLE mytab (id NUMBER, salary NUMBER, name VARCHAR2(40));
//   INSERT INTO mytab (id, salary, name) VALUES (1, 100, 'Chris');
//   COMMIT;

$conexión oci_connect('hr''welcome''localhost/XE');
if (!
$conexión) {
    
$m oci_error();
    
trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$stid oci_parse($conexión'SELECT ROWID, name FROM mytab WHERE id = :id_bv FOR UPDATE');
$id 1;
oci_bind_by_name($stid':id_bv'$id);
oci_execute($stid);
$fila oci_fetch_array($stidOCI_ASSOC+OCI_RETURN_NULLS);
$rid $fila['ROWID'];
$nombre $fila['NAME'];

// Cambiar el nombre a mayúsculas y guardar los cambios
$nombre strtoupper($nombre);
$stid oci_parse($conexión'UPDATE mytab SET name = :n_bv WHERE ROWID = :r_bv');
oci_bind_by_name($stid':n_bv'$nombre);
oci_bind_by_name($stid':r_bv'$rid, -1OCI_B_ROWID);
oci_execute($stid);

// La tabla contiene ahora 1, 100, CHRIS

oci_free_statement($stid);
oci_close($conexión);

?>

Ejemplo #9 Vinculación de un ROWID sobre INSERT

<?php

// Este ejemplo inserta un id y un nombre, y luego actualiza el salario
// Cree la tabla con:
//   CREATE TABLE mytab (id NUMBER, salary NUMBER, name VARCHAR2(40));
//
// Basado en el ejemplo original de ROWID de thies at thieso dot net (980221)

$conexión oci_connect('hr''welcome''localhost/XE');
if (!
$conexión) {
    
$m oci_error();
    
trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$sql "INSERT INTO mytab (id, name) VALUES(:id_bv, :name_bv)
        RETURNING ROWID INTO :rid"
;

$ins_stid oci_parse($conexión$sql);

$id_fila oci_new_descriptor($conexiónOCI_D_ROWID);
oci_bind_by_name($ins_stid":id_bv",   $id,    10);
oci_bind_by_name($ins_stid":name_bv"$nombre,  32);
oci_bind_by_name($ins_stid":rid",     $id_fila, -1OCI_B_ROWID);

$sql "UPDATE mytab SET salary = :salary WHERE ROWID = :rid";
$upd_stid oci_parse($conexión$sql);
oci_bind_by_name($upd_stid":rid"$id_fila, -1OCI_B_ROWID);
oci_bind_by_name($upd_stid":salary"$salario,   32);

// Los identificadores y los nombres a insertar
$datos = array(1111 => "Larry",
              
2222 => "Bill",
              
3333 => "Jim");

// El salario para cada persona
$salario 10000;

// Insertar e inmediatamente actualizar cada fila
foreach ($datos as $id => $nombre) {
    
oci_execute($ins_stid);
    
oci_execute($upd_stid);
}

$id_fila->free();
oci_free_statement($upd_stid);
oci_free_statement($ins_stid);

// Mostrar las nuevas filas
$stid oci_parse($conexión"SELECT * FROM mytab");
oci_execute($stid);
while (
$fila oci_fetch_array($stidOCI_ASSOC+OCI_RETURN_NULLS)) {
    
var_dump($fila);
}

oci_free_statement($stid);
oci_close($conexión);

?>

Ejemplo #10 Vinculación para una función almacenada de PL/SQL

<?php

//  Antes de ejecutar este programa de PHP, cree una función almacenada en
//  SQL*Plus o SQL Developer:
//
//  CREATE OR REPLACE FUNCTION myfunc(p IN NUMBER) RETURN NUMBER AS
//  BEGIN
//      RETURN p * 3;
//  END;

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

$p 8;

$stid oci_parse($conexión'begin :r := myfunc(:p); end;');
oci_bind_by_name($stid':p'$p);

// El valor devuelto es un vínculo OUT. El tipo predeterminado será una cadena,
// por lo que vincular 40 significa que serán devueltos 40 dígitos
// como máximo.
oci_bind_by_name($stid':r'$r40);

oci_execute($stid);

print 
"$r\n";   // imprime 24

oci_free_statement($stid);
oci_close($conexión);

?>

Ejemplo #11 Vinculación de parámetros para un procedimiento almacenado de PL/SQL

<?php

//  Antes de ejecutar este programa de PHP, cree un procedemiento almacenado en
//  SQL*Plus o SQL Developer:
//
//  CREATE OR REPLACE PROCEDURE myproc(p1 IN NUMBER, p2 OUT NUMBER) AS
//  BEGIN
//      p2 := p1 * 2;
//  END;

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

$p1 8;

$stid oci_parse($conexión'begin myproc(:p1, :p2); end;');
oci_bind_by_name($stid':p1'$p1);

// El segundo parámetro del procedimiento es un vínculo OUT. El tipo predeterminado
// será una cadena, por lo que vincular 40 significa que serán devueltos 40 dígitos
// como máximo.
oci_bind_by_name($stid':p2'$p240);

oci_execute($stid);

print 
"$p2\n";   // imprime 16

oci_free_statement($stid);
oci_close($conexión);

?>

Ejemplo #12 Vinculación de una columna CLOB

<?php

// Antes de ejecutarlo, cree la tabla:
//     CREATE TABLE mytab (mykey NUMBER, myclob CLOB);

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

$mykey 12343;  // clave arbitraria para este ejemplo;

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

$stid oci_parse($conexión$sql);
$clob oci_new_descriptor($conexiónOCI_D_LOB);
oci_bind_by_name($stid":mykey"$mykey5);
oci_bind_by_name($stid":myclob"$clob, -1OCI_B_CLOB);
oci_execute($stidOCI_DEFAULT);
$clob->save("A very long string");

oci_commit($conexión);

// Obtener los datos CLOB

$consulta 'SELECT myclob FROM mytab WHERE mykey = :mykey';

$stid oci_parse ($conexión$consulta);
oci_bind_by_name($stid":mykey"$mykey5);
oci_execute($stid);

print 
'<table border="1">';
while (
$fila oci_fetch_array($stidOCI_ASSOC+OCI_RETURN_LOBS)) {
    print 
'<tr><td>'.$fila['MYCLOB'].'</td></tr>';
    
// En un bucle, liberar la variable grande de la 2ª obtención reduce en uso de memoria de picos de PHP
    
unset($fila);  
}
print 
'</table>';

?>

Ejemplo #13 Vincular un BOOLEAN de PL/SQL

<?php

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

$plsql 
  
"begin
    :output1 := true;
    :output2 := false;
   end;"
;

$s oci_parse($c$plsql);
oci_bind_by_name($s':output1'$output1, -1OCI_B_BOL);
oci_bind_by_name($s':output2'$output2, -1OCI_B_BOL);
oci_execute($s);
var_dump($output1);  // true
var_dump($output2);  // false

?>

Valores devueltos

Devuelve TRUE en caso de éxito o FALSE en caso de error.

Notas

Advertencia

No use magic_quotes_gpc o addslashes() y oci_bind_by_name() simultáneamente, ya que no es necesario el entrecomillado. Cualquier comilla aplicada mágicamente será escrita en la base de datos debido a que oci_bind_by_name() inserta los datos textualmente y no elimina las comillas o los caracteres de escape.

Nota:

Si vincula una cadena con una columna CHAR en una cláusula WHERE, recuerde que Oracle utiliza una semántica de comparación de relleno en blanco para columnas CHAR. La variable de PHP debería estar rellena con espacios en blanco a la misma longitud que la columna para que la cláusula WHERE tenga éxito.

Nota:

El argumento variable de PHP es una referencia. Algunas formas de bucles no funcionan como era de esperar:

<?php
foreach ($array as $clave => $valor)  {
    
oci_bind_by_name($stid$clave$valor);
}
?>

Esto vincula cada clave a la ubicación de $valor, por lo que todas las variables vinculadas terminaran apuntando al valor de la última interación del bucle. En su lugar, se ha de utilizar lo siguiente:

<?php
foreach ($array as $clave => $valor) {
    
oci_bind_by_name($stid$clave$array[$clave]);
}
?>

Ver también

add a note add a note

User Contributed Notes 9 notes

up
1
adrian dot crossley at hesa dot ac dot uk
5 years ago
Sometimes you get the error "ORA-01461: can bind a LONG value only for insert into a LONG column".  This error is highly misleading especially when you have no LONG columns or LONG values.

From my testing it seems this error can be caused when the value of a bound variable exceeds the length allocated.

To avoid this error make sure you specify lengths when binding varchars e.g.
<?php
oci_bind_by_name
($stmt,':string',$string, 256);
?>

And for numerics use the default length (-1) but tell oracle its an integer e.g.
<?php
oci_bind_by_name
($stmt,':num',$num, -1, SQLT_INT);
?>
up
1
ajitsingh4u at gmail dot com
6 years ago
//Calling Oracle Stored Procedure
//I assume that you have a users table and three columns in users table i.e. id, user, email in oracle
// For example I made connection in constructor, you can modify as per your requirement.
//http://www.devshed.com/c/a/PHP/Understanding-Destructors-in-PHP-5/1/
<?php
class Users{
    private
$connection;
   
    public function
__construct()
    {
       
$this->connection = oci_connect("scott", "tiger", $db); // Establishes a connection to the Oracle server;
   
}

    public function
selectUsers($start_index=1, $numbers_of_rows=20)
    {
       
$sql ="BEGIN sp_users_select(:p_start_index, :p_numbers_of_rows, :p_cursor, :p_result); END;";
       
$stmt = oci_parse($this->connection, $sql);

       
//Bind in parameter
       
oci_bind_by_name($stmt, ':p_start_index', $start_index, 20);
       
oci_bind_by_name($stmt, ':p_numbers_of_rows', $numbers_of_rows, 20);

       
//Bind out parameter
       
oci_bind_by_name($stmt, ':p_result', $result, 20); // returns 0 if stored procedure succeessfully executed.

        //Bind Cursor
       
$p_cursor = oci_new_cursor($this->connection);
       
oci_bind_by_name($stmt, ':p_cursor', $p_cursor, -1, OCI_B_CURSOR);

       
// Execute Statement
       
oci_execute($stmt);
       
oci_execute($p_cursor, OCI_DEFAULT);

       
oci_fetch_all($p_cursor, $cursor, null, null, OCI_FETCHSTATEMENT_BY_ROW);

        echo
$result;
        echo
'<br>';
       
var_dump($cursor); // $cursor is an associative array so we can use print_r() to print this data.
        // you can return data from this function to use it at your user interface.
   
}

    public function
deleteUser($id)
    {
       
$sql ="BEGIN sp_user_delete(:p_id, :p_result); END;";
       
$stmt = oci_parse($this->connection, $sql);

       
// bind in and out variables
       
oci_bind_by_name($stmt, ':p_id', $id, 20);
       
oci_bind_by_name($stmt, ':p_result', $result, 20);

       
//Execute the statement
       
$check = oci_execute($stmt);

        if(
$check == true)
       
$commit = oci_commit($this->connection);
        else
       
$commit = oci_rollback($this->connection);

        return
$result;
    }
   
   
// You can make function for insert ,update using above two functions

}
?>
up
0
xorinox at gmx dot ch
8 days ago
Working with Oracle and raw types in and out worked like the following for me.

<?php
 
/*oracle procedure
  procedure open_session(
    i_instance_id in raw,
    o_session_id out raw,
    o_errcode out number,
    o_errmsg out varchar2
  ); 
  */

  //open database
 
$conn = DBOpen( DB_DEV_USER );

 
//get session id
 
$sql = "begin p_loader.open_session( hextoraw( :instance_id ), :session_id, :errcode, :errmsg ); end;";
 
$stmt = oci_parse( $conn, $sql );
 
$instanceId = DB_INSTANCE_ID;
 
oci_bind_by_name( $stmt, ":instance_id", $instanceId, 1, SQLT_CHR );
 
oci_bind_by_name( $stmt, ":session_id", $sessionId, 16, SQLT_BIN );
 
oci_bind_by_name( $stmt, ":errcode", $errcode, 12, SQLT_INT );
 
oci_bind_by_name( $stmt, ":errmsg", $errmsg, 4000, SQLT_CHR );
 
 
oci_execute( $stmt );
 
$sessionId = bin2hex( $sessionId ); //now this is a hex string
 
  //close database
 
DBClose( $conn );
?>
up
0
jjeffman at cpovo.net
5 months ago
It is very important to set up the maxlength of the returning parameter (:r), even when it is returning a number, otherwise the ORA-01460 exception (unimplemented or unreasonable conversion requested) may be raised.
up
0
abiyi2000 at yahoo dot com
3 years ago
I unfortunately spent the whole day trying to make this work as part of OCI bind_by_name insert:

<?php
     
if(is_numeric($v2)){
       
oci_bind_by_name($stmth, $bvar, $v2,  -1, OCI_B_INT);
      }else{
       
$v2 = (string) $v2;
       
oci_bind_by_name($stmth, $bvar, $v2, -1, SQLT_CHR);
      }
?>

The string field is always inserting correctly w/o any truncation. The string field is a  varchar2(160) CHAR, but the data used to populate it is 40 chars in length.

The numeric part is of Type Number in the database which is being used to store unix time (10 digit seconds since 1970/01/01.

The problem, the insert was truncating to 9 digits with some bogus value not even related to the input i.e., it's not just a matter of dropping the leftmost or rightmost digit, it'll just insert a 9 digit bogus number.

The only way I was able to resolve this for the numeric field was to set the maxlength to 8 (not 10 which is the number of digits in the input):

<?php
     
if(is_numeric($v2)){
       
oci_bind_by_name($stmth, $bvar, $v28, OCI_B_INT);
      }else{
       
$v2 = (string) $v2;
       
oci_bind_by_name($stmth, $bvar, $v2, -1, SQLT_CHR);
      }
?>

Hopefully you'll see this soon before you expend a lot of time repeating the same problem I had.
up
0
avenger at php dot net
5 years ago
Dont forget the 5th parameter: $type. It's will slowly your code some times. Eg:

<?php
$sql
= "select * from (select * from b xxx) where rownum < :rnum";
$stmt = OCIParse($conn,$sql);
OCIBindByName($stmt, ":rnum", $NUM, -1);
OCIExecute($stmt);
?>

Below code was slow 5~6 time than not use bind value.Change the 3rd line to:

<?php
OCIBindByName
($stmt, ":rnum", $NUM, -1, SQLT_INT);
?>

will resloved this problem.

This issue is also in the ADODB DB class(adodb.sf.net), you will be careful for use the SelectLimit method.
up
0
Anonymous
7 years ago
This is what the old OCI_B_* constants are now called:
(PHP 5.1.6 win32)

OCI_B_NTY - SQLT_NTY
OCI_B_BFILE - SQLT_BFILEE
OCI_B_CFILEE - SQLT_CFILEE
OCI_B_CLOB - SQLT_CLOB
OCI_B_BLOB - SQLT_BLOB
OCI_B_ROWID - SQLT_RDD
OCI_B_CURSOR - SQLT_RSET
OCI_B_BIN - SQLT_BIN
OCI_B_INT - SQLT_INT
OCI_B_NUM - SQLT_NUM
up
0
Chris Delcamp
7 years ago
This is an example of returning the primary key from an insert so that you can do inserts on other tables with foreign keys based on that value.  The date is just used to provied semi-unique data to be inserted.

$conn = oci_connect("username", "password")
$stmt = oci_parse($conn, "INSERT INTO test (test_msg) values (:data) RETURN test_id INTO :RV");
$data = date("d-M-Y H:i:s");
oci_bind_by_name($stmt, ":RV", $rv, -1, SQLT_INT);
oci_bind_by_name($stmt, ":data", $data, 24);
oci_execute($stmt);
print $rv;
up
0
hfuecks at nospam dot org
9 years ago
Note that there have been some changes on the constant identifiers and the documentation is currently not entirely accurate.

Running the following script;

<?php
foreach (array_keys(get_defined_constants()) as $const) {
    if (
preg_match('/^OCI_B_/', $const) ) {
        print
"$const\n";
    }
}
?>

Under PHP 4.4.0 I get;

OCI_B_SQLT_NTY < renamed to OCI_B_NTY with PHP5
OCI_B_BFILE
OCI_B_CFILEE
OCI_B_CLOB
OCI_B_BLOB
OCI_B_ROWID
OCI_B_CURSOR
OCI_B_BIN

Under PHP 5.0.4 I get;

OCI_B_NTY
OCI_B_BFILE < docs are wrong right now
OCI_B_CFILEE < docs are wrong right now
OCI_B_CLOB
OCI_B_BLOB
OCI_B_ROWID
OCI_B_CURSOR
OCI_B_BIN < it's a mystery
To Top