Skip to main content

PL/SQL

Come Oracle Forms Developer di solito i blocchi vengono basati direttamente su tabelle, view o al massimo select SQL? Ma Forms offre altre opzioni che non vengono documentate, come trigger e procedure PL/SQL. La mancanza di documentazione è frustrate. Qui trovate un link interessante e più sotto un esempio.

Thanks to "Craig's Oracle Stuff". Info taken from here

Demo completa

Using XML-SQL Utility (XSU)

XML-SQL Utility (XSU) fornisce un sistema semplice di trasfomazione mappando ogni query SQL con ZML e viceversa. XSU fornisce le funzionalità di base per ottenre e salvare dati da e verso il database.

DECLARE
  queryCtx dbms_xmlquery.ctxType;
  result CLOB;
BEGIN
  -- set up the query context
  queryCtx := dbms_xmlquery.newContext(
    'SELECT ''Miao'' tag1
          , ''Ciao''   tag2
          , ''Bau''    tag3
       FROM dual'
  );
  
  dbms_xmlquery.setRowTag(
      queryCtx
    , 'header'
  );
  dbms_xmlquery.setRowSetTag(
      queryCtx
    , 'message'
  );  
  result := dbms_xmlquery.getXml(queryCtx);
  dbms_output.put_line(result);
  dbms_xmlquery.closeContext(queryCtx);   
end;

E questo è il risultato:

<?xml version = '1.0'?>
<message>
   <header num="1">
      <TAG1>Miao</TAG1>
      <TAG2>Ciao</TAG2>
      <TAG3>Bau</TAG3>
   </header>
</message>

Using XML-SQL Utility (XSU)

XML-SQL Utility (XSU) provides a simple way of achieving data transformation by mapping any SQL query to XML and vice versa. XSU provides the basic functionality to get and put data to and from a database.

DECLARE
  queryCtx dbms_xmlquery.ctxType;
  result CLOB;
BEGIN
  -- set up the query context
  queryCtx := dbms_xmlquery.newContext(
    'SELECT ''Miao'' tag1
          , ''Ciao''   tag2
          , ''Bau''    tag3
       FROM dual'
  );
 
  dbms_xmlquery.setRowTag(
      queryCtx
    , 'header'
  );
  dbms_xmlquery.setRowSetTag(
      queryCtx
    , 'message'
  );  
  result := dbms_xmlquery.getXml(queryCtx);
  dbms_output.put_line(result);
  dbms_xmlquery.closeContext(queryCtx);   
end; 

And this is the result:

<?xml version = '1.0'?>
<message>
   <header num="1">
      <TAG1>Miao</TAG1>
      <TAG2>Ciao</TAG2>
      <TAG3>Bau</TAG3>
   </header>
</message>

Questo codice PL/SQL converte una variabile clob a una blob.

function clob_to_blob(c in clob) return blob is
    -- typecasts CLOB to BLOB (binary conversion)
   pos PLS_INTEGER := 1;
   buffer RAW( 32767 );
   res BLOB;
   lob_len PLS_INTEGER := DBMS_LOB.getLength( c );
BEGIN
   DBMS_LOB.createTemporary( res, TRUE );
   DBMS_LOB.OPEN( res, DBMS_LOB.LOB_ReadWrite );
   
   LOOP
    buffer := UTL_RAW.cast_to_raw( DBMS_LOB.SUBSTR( c, 16000, pos ) );

    IF UTL_RAW.LENGTH( buffer ) > 0 THEN
       DBMS_LOB.writeAppend( res, UTL_RAW.LENGTH( buffer ), buffer );
    END IF;

    pos := pos + 16000;
    EXIT WHEN pos > lob_len;
   END LOOP;

   RETURN res;
END;
Oracle docs
SQL Data TypesJDBC Type CodesStandard Java TypesOracle Extension Java Types
  STANDARD JDBC 1.0 TYPES:    
CHAR java.sql.Types.CHAR java.lang.String oracle.sql.CHAR
VARCHAR2 java.sql.Types.VARCHAR java.lang.String oracle.sql.CHAR
LONG java.sql.Types.LONGVARCHAR java.lang.String oracle.sql.CHAR
NUMBER java.sql.Types.NUMERIC java.math.BigDecimal oracle.sql.NUMBER
NUMBER java.sql.Types.DECIMAL java.math.BigDecimal oracle.sql.NUMBER
NUMBER java.sql.Types.BIT boolean oracle.sql.NUMBER
NUMBER java.sql.Types.TINYINT byte oracle.sql.NUMBER
NUMBER java.sql.Types.SMALLINT short oracle.sql.NUMBER
NUMBER java.sql.Types.INTEGER int oracle.sql.NUMBER
NUMBER java.sql.Types.BIGINT long oracle.sql.NUMBER
NUMBER java.sql.Types.REAL float oracle.sql.NUMBER
NUMBER java.sql.Types.FLOAT double oracle.sql.NUMBER
NUMBER java.sql.Types.DOUBLE double oracle.sql.NUMBER
RAW java.sql.Types.BINARY byte[] oracle.sql.RAW
RAW java.sql.Types.VARBINARY byte[] oracle.sql.RAW
LONGRAW java.sql.Types.LONGVARBINARY byte[] oracle.sql.RAW
DATE java.sql.Types.DATE java.sql.Date oracle.sql.DATE
DATE java.sql.Types.TIME java.sql.Time oracle.sql.DATE
TIMESTAMP java.sql.Types.TIMESTAMP javal.sql.Timestamp oracle.sql.TIMESTAMP
  STANDARD JDBC 2.0 TYPES:    
BLOB java.sql.Types.BLOB java.sql.Blob oracle.sql.BLOB
CLOB java.sql.Types.CLOB java.sql.Clob oracle.sql.CLOB
user-defined object java.sql.Types.STRUCT java.sql.Struct oracle.sql.STRUCT
user-defined reference java.sql.Types.REF java.sql.Ref oracle.sql.REF
user-defined collection java.sql.Types.ARRAY java.sql.Array oracle.sql.ARRAY
  ORACLE EXTENSIONS:    
BFILE oracle.jdbc.OracleTypes.BFILE NA oracle.sql.BFILE
ROWID oracle.jdbc.OracleTypes.ROWID NA oracle.sql.ROWID
REF CURSOR oracle.jdbc.OracleTypes.CURSOR java.sql.ResultSet oracle.jdbc.OracleResultSet
TIMESTAMP oracle.jdbc.OracleTypes.TIMESTAMP java.sql.Timestamp oracle.sql.TIMESTAMP
TIMESTAMP WITH TIME ZONE oracle.jdbc.OracleTypes.TIMESTAMPTZ java.sql.Timestamp oracle.sql.TIMESTAMPTZ
TIMESTAMP WITH LOCAL TIME ZONE oracle.jdbc.OracleTypes.TIMESTAMPLTZ java.sql.Timestamp oracle.sql.TIMESTAMPLTZ

This PL/SQL code convert a clob variable to a blob one.


function clob_to_blob(c in clob) return blob is
    -- typecasts CLOB to BLOB (binary conversion)
   pos PLS_INTEGER := 1;
   buffer RAW( 32767 );
   res BLOB;
   lob_len PLS_INTEGER := DBMS_LOB.getLength( c );
BEGIN
   DBMS_LOB.createTemporary( res, TRUE );
   DBMS_LOB.OPEN( res, DBMS_LOB.LOB_ReadWrite );
   
   LOOP
    buffer := UTL_RAW.cast_to_raw( DBMS_LOB.SUBSTR( c, 16000, pos ) );

    IF UTL_RAW.LENGTH( buffer ) > 0 THEN
       DBMS_LOB.writeAppend( res, UTL_RAW.LENGTH( buffer ), buffer );
    END IF;

    pos := pos + 16000;
    EXIT WHEN pos > lob_len;
   END LOOP;

   RETURN res;
END;

This construct updates every column so use with care. May cause increased redo, undo, and foreign key locking issues.

DECLARE
  p_rec  t%ROWTYPE;
BEGIN
 ...
 
  p_rec.column_x := 'AA';
  p_rec.column_y := 'BB';
 
 ...
 
  UPDATE t
  SET ROW = trec
  WHERE column_z = 'CC';
 
 ....
END;

Info taken from http://psoug.org/reference/update.html

Questo costrutto aggiorna ogni colonna di un record con i dati contenuti in un variabile difinita con ROWTYPE. Potrebbe quindi innescare lock delle chiavi di una foreign key.

DECLARE
  p_rec  t%ROWTYPE;
BEGIN
 ...
 
  p_rec.column_x := 'AA';
  p_rec.column_y := 'BB';
 
 ...
 
  UPDATE t
  SET ROW = trec
  WHERE column_z = 'CC';
 
 ....
END;

Info taken from http://psoug.org/reference/update.html