Skip to main content

Oracle

Il package DBMS_FILE_TRANSFER mette a disposizione procedure per copiare file binary all'interno di un database o rta database diversi. Per esempio:

  1. Copia file da una source directory all' altra. Le due directory possono essere entrambe sul filesystem locale, oppure entrambe nell Automatic Storage Management (ASM) disk group, o anche essere in situazioni miste in entrambe le direzioni.
  2. Si sollega ad un db remoto e legge un file remoto creandone una copia sul filesystem o ASM locali
  3. Legge il filesystem locale o ASM e si collega ad un database remoto per crearvi una copia del file

NB. Non lavora sul DB nel senso stretto del termine, vale a dire su colonne LOB o CLOB.

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

Questo è un esempio:

procedure load_attachment(dir in varchar2, nam in varchar2) is
 fl BFILE;
 att blob;
 begin
 Dbms_Lob.createtemporary(att, TRUE, Dbms_Lob.CALL); 
 fl := BFileName(dir, nam);
 if (dbms_lob.fileexists(fl) = 1) then
 
 Dbms_Lob.fileopen(fl, Dbms_Lob.LOB_READONLY);
 Dbms_Lob.loadfromfile(att, fl, Dbms_Lob.getlength(fl));
 Dbms_Lob.fileclose(fl);

....
 else
 dbms_output.put_line('File doesn't exists!');
 end if;  
 end;

Se ottenete l' errore Oracle ORA-22275 - invalid LOB locator specified, forse avete dimenticato l' istruzione Dbms_Lob.createtemporary.

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

E' spesso utile accedere ai dati contenuti in una vriabile XML TYpe, usando l' SQL come se fossero in una tabella o vista.

XML ha per sua stessa natura una struttura gerarchica. Di conseguenza viene facile pensare ad un file XML come a record di tabelle legate tra loro da relazioni master-detail.

Pensiamo ad un documento XML memorizzato nella colonna XML Type di una tabella Oracle:

<root> 
   <master id ='A'> 
    <info>First Header</info> 
      <detail> 
        <info>Detail 1</info> 
      </detail> 
      <detail> 
        <info>Detail 2</info> 
      </detail> 
   </master> 
   <master id = 'B'> 
      <info>Second Header</info> 
      <detail> 
           <info>Detail 3</info> 
      </detail> 
   </master>
</root>

Creeremo due viste ("dumb_master" e "dumb_detail") connesse da relazione master-detail relationship e popolate dai dati contenuti nell' XML Document della colonna dumb.dumber.

L'errore in questione, Oracle ORA-00054: resource busy and acquire with NOWAIT specified  (in italiano, ORA-00054: risorsa occupata, acquisizione con NOWAIT specificato o timeout scaduto), viene lanciato quando si tenta di acquisire un lock su una risorsa in modalità NOWAIT, e la risolrsa risulta già loccata da un altra sessione. Senza NOWAIT il codice resterebbe bloccato in attesa del rilascio del lock. Con NOWAIT il codice non si blocca e scatena l'eccezione.

Intercettare l'errore con un blocco exception è molto semplice, e vi permette di gestire la mancata acquisizione del lock in modo pulito:

DECLARE
  resource_busy EXCEPTION;
  PRAGMA EXCEPTION_INIT(resource_busy, -54);
BEGIN
  ...
   select {column_list} from {table_name} where {where_clause} for update nowait;
  ....
EXCEPTION
WHEN resource_busy THEN
  /*
* Il codice di gestione
* della mancata acquisizione del lock va qui
*/ END;

Esempio di utilizzo del package EXEC_SQL per eseguire istruzioni SQL dinamiche all'interno di Oracle Forms o Reports.

Esempio di utilizzo del package EXEC_SQL per eseguire istruzioni SQL dinamiche all'interno di Oracle Forms o Reports.

Here's a code example:

procedure load_attachment(dir in varchar2, nam in varchar2) is
fl BFILE;
att blob;
begin
Dbms_Lob.createtemporary(att, TRUE, Dbms_Lob.CALL);
fl := BFileName(dir, nam);
if (dbms_lob.fileexists(fl) = 1) then

Dbms_Lob.fileopen(fl, Dbms_Lob.LOB_READONLY);
Dbms_Lob.loadfromfile(att, fl, Dbms_Lob.getlength(fl));
Dbms_Lob.fileclose(fl);

....
else
dbms_output.put_line('File doesn't exists!');
end if;  
end;

If you get Oracle error ORA-22275 - invalid LOB locator specified, maybe you forgot the Dbms_Lob.createtemporary instruction.

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