miércoles, 21 de agosto de 2013

Cursores Dinamicos en ORACLE

Estos son métodos para crear cursores dinamicos, esto sirve cuando se necesita mandar un SQL o una tabla en una variable y usarlar en un mismo cursor

Método 1:

declare
   --Se crea un objeto tipo cursor
   TYPE tipoCursor IS REF CURSOR;
   --Se define una variable con el objeto tipo cursor
   cursorDinamico tipoCursor;
  --Variable que obtiene el SQL o TABLA a usar
 SQL_DINAMICO varchar2(100) := 'SELECT TO_CHAR(SYSDATE,'||CHR(39)||'MM'||CHR(39)||') campo1, TO_CHAR(SYSDATE,'||CHR(39)||'RRRR'||CHR(39)||') campo2 FROM DUAL';

--estos son los campos que van a ser usados como resultado de cada uno de los campos que va a devolver el cursor
 
  campo1 varchar2(200);
   campo2 varchar2(200);

  begin
-- Se abre el cursor
   open cursorDinamico for
      'SELECT * FROM (' || SQL_DINAMICO||') ';
   loop
      --Se almacena cada uno de los campos que devuelve la consulta en variables para ser usadas
      fetch cursorDinamico into campo1, campo2;
      exit when cursorDinamico%NOTFOUND;
      dbms_output.put_line(campo1||' '||campo2);
   end loop;
 
   close cursorDinamico;
    end;

Método 2 para uso avanzado con definición de vectores dinámicos:


declare
   SQL_DINAMICO varchar2(100) := 'SELECT TO_CHAR(SYSDATE,'||CHR(39)||'MM'||CHR(39)||') campo1, TO_CHAR(SYSDATE,'||CHR(39)||'RRRR'||CHR(39)||') campo2 FROM DUAL';

   v_cursor integer := dbms_sql.open_cursor;//Define un objeto tipo cursor
   v_desctab dbms_sql.desc_tab; --Define un objeto dinámico parecido a una tabla (Tiene internamente campos, tamaño, valor)
   v_numcols integer; 
   v_value varchar2(4000);
   v_status integer;
   name_array dbms_sql.varchar2_table;//Define un array y es usado como cualquier array en cualquier lenguaje se invoca name_array(posicion)
begin
   dbms_sql.parse( v_cursor, SQL_DINAMICO, dbms_sql.native );--Esto permite interpretar el texto plano y lo convierte a sql nativo
   dbms_sql.describe_columns( v_cursor, v_numcols, v_desctab );--Esto Crea todos los campos del cursor
--   dbms_output.put_line(v_numcols);--Con esto permite contar la cantidad de columnas que tiene el cursor
 
    --Para esto hay que investigar un poco mas pero permite definir cada uno de los campos con el tamaño que uno desee  
    for i in 1 .. v_numcols loop
        dbms_sql.define_column(v_cursor, i, v_value, 4000);
        --v_desctab(i).col_name
    end loop;
   
    --Se ejecuta el cursor
    v_status := dbms_sql.execute(v_cursor);
   
    --Se recorre el cursor en filas y columnas
    while ( dbms_sql.fetch_rows(v_cursor) > 0 ) loop  
        for i in 1 .. v_numcols loop
            dbms_sql.column_value( v_cursor, i, v_value );
            --En este caso se almacena el valor en un array
            name_array(i):=v_value;         
        end loop;
        dbms_output.put_line(name_array(1)||' '||name_array(2));--Imprimo los valores del campo 1 y el 2
      
    end loop;
  
  
  
end; 

Es importante tomar en cuenta que la librería de "dbms_sql" es muy poderosa, permite ver hasta tipos de datos de una tabla y nombres de campos