How to execute a Stored Procedure Oracle with ZF2

I was some problems to execute an oracle stored procedure in ZF2 with out params.

The following is an example, how finally I implemented the solution.

Procedure


CREATE OR REPLACE procedure sp_tmp(rtn out char) AS
begin

rtn := '1';

end sp_tmp;
/

 Call from ZF2 Model


        $adapter = $this->tableGateway->adapter;
        $statement = $adapter->createStatement();
        $statement->prepare("begin sp_tmp(:output); end;");

        $parameterContainer = new \Zend\Db\Adapter\ParameterContainer;
        //Uncomment this if you want to add IN params
        //$parameterContainer->offsetSet('inParam', '', $parameterContainer::TYPE_STRING); 
        $parameterContainer->offsetSetReference('output', 'output'); // Out parameter
        $statement->setParameterContainer($parameterContainer);
        $statement->execute();

        var_dump($parameterContainer->getNamedArray());

 Finally I got this:

array (size=1)
  'output' => &string '1' (length=1)

Auto increment for oracle

Oracle does *NOT* support auto_increment keys like mysql natively so there are different ways to emulate it.

Particularly I prefer to create a SEQUENCE and update it through a trigger.

-- Creation of table
CREATE TABLE user(
 user_id INTEGER NOT NULL ,
 name VARCHAR2(15),
 PRIMARY KEY ( user_id )
);

-- Creation of sequence
CREATE SEQUENCE seq_user_id
    START WITH 1
    INCREMENT BY 1
NOMAXVALUE;

-- Creation of trigger
CREATE TRIGGER trg_user_seq
BEFORE INSERT ON user
FOR EACH ROW
 BEGIN
   SELECT seq_user_id.nextval INTO :new.user_id 
     FROM dual;
 END;

Insert statement

    INSERT INTO user (name) VALUES('Francis');

Data Table

   USER_ID NAME           
---------- ---------------
         1 Francis            

SQLDeveloper en Ubuntu

Para instalar SQLDeveloper en Ubuntu debemos descargar SQLDeveloper para Linux desde la página oficial de Oracle. (http://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/)

Nos dirigimos a la carpeta donde lo descargamos:

fragote@fragote:~/Documents/Instaladores/SQLDeveloper$ ll
total 236912
drwxrwxr-x 2 fragote fragote 4096 sep 7 16:06 ./
drwxr-xr-x 17 fragote fragote 4096 sep 7 16:06 ../
-rw-rw-r-- 1 fragote fragote 242580060 sep 7 15:32 sqldeveloper-4.0.2.15.21-1.noarch.rpm

Convertimos el archivo de rpm (formato para CentOS) por un *.deb (paquete para ubuntu)

fragote@fragote:~/Documents/Instaladores/SQLDeveloper$ sudo alien --scripts -d sqldeveloper-4.0.2.15.21-1.noarch.rpm 
sqldeveloper_4.0.2.15.21-2_all.deb generated

Pasamos a instalar el paquete

fragote@fragote:~/Documents/Instaladores/SQLDeveloper$ sudo dpkg --install sqldeveloper_4.0.2.15.21-2_all.deb 
Selecting previously unselected package sqldeveloper.
(Reading database ... 410367 files and directories currently installed.)
Preparing to unpack sqldeveloper_4.0.2.15.21-2_all.deb ...
Unpacking sqldeveloper (4.0.2.15.21-2) ...
Setting up sqldeveloper (4.0.2.15.21-2) ...

Utilizamos el script para setear la ruta de java para mi caso ‘/usr/lib/jvm/java-7-oracle’

fragote@fragote:~/Documents/Instaladores/SQLDeveloper$ sudo /opt/sqldeveloper/sqldeveloper.sh
 Oracle SQL Developer
 Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
Type the full pathname of a JDK installation (or Ctrl-C to quit), the path will be stored in /home/fragote/.sqldeveloper/4.0.0/product.conf
/usr/lib/jvm/java-7-oracle

Finalmente podemos abrir SQLDeveloper, por terminal de la siguiente forma

~$ sqldeveloper
sqldeveloper

sqldeveloper

Error ORA-06502 Oracle y PHP

El problema se presentó usando PHP con Zend Framework 1 y Oracle 11G más detalles a continuación.

Oracle stored procedure:

CREATE OR REPLACE PROCEDURE FGONZALES.GRABA_PRUEBA
(ls_parametro varchar2
 ls_mensaje out varchar2)

Llamando al stored procedure desde PHP:

$param = 'test ';
$mensaje = ''; //O nulo
$params = array(
	'PARAM' => $param,
	'MENSAJE' => &$mensaje,
);

$sql = 'BEGIN 
GRABA_PRUEBA(
	:PARAM,
	:MENSAJE
);
END;'; 
$stmt = $db->prepare($sql);
$stmt->execute($params);

$respuesta = $mensaje;

Con los pasos anteriores obtengo el siguiente error por parte de Oracle:

6502 ORA-06502: PL/SQL: error : 
buffer de cadenas de caracteres demasiado 
pequeño numerico o de valor.

Para este caso ls_mensaje del stored procedure solo puede guardar un caracter, si pasa de uno aparece el error ORA-06502.
Mi solución fue la siguente:

$mensaje = str_repeat(' ', 4000);

Declarar la variable con un máximo tamaño para VARCHAR2 de Oracle.