Dieser Kurs zur Datenbankprogrammierung mit PL/SQL vermittelt zunächst eine Einführung zu PL/SQL und untersucht anschließend die Vorteile dieser leistungsstarken Programmiersprache. Im Rahmen praktischer Übungen machen Sie sich unter Anleitung qualifizierter Oracle-Dozenten mit der Entwicklung von Stored Procedures, Stored Functions, Packages usw. vertraut.

  OAEC1oracle ptnr clr rgb

Learn Oracle from Oracle - Original Oracle University Seminar

Mit dem vorliegenden Kurs Oracle Database: Introduction to SQL werden Ihnen Kenntnisse zum Erstellen von Unterabfragen, zum Zusammenfassen mehrerer Abragen mit einem Mengenoperator zu einer einzelnen Abfrage und zum Erstellen von Berichten aus aggregierten Daten mithilfe von Gruppenfunktionen vermittelt. Diese und weitere Kenntnisse werden mithilfe praktischer Übungen vertieft.

  OAEC1oracle ptnr clr rgb

Learn Oracle from Oracle - Original Oracle University Seminar

Oft wird die Frage gestellt, wie können Abhängigkeiten von PL/SQL-Objekten analysiert werden. Hierfür liefert die View DBA_DEPENDENCIES zwar die direkten, leider nicht die indirekten Abhängigkeiten. Die folgenden Prozeduren und Funktionen geben hier Hilfe.

Die folgende Prozedur gibt die von einem übergebenen Objekt abhängigen Objekte zurück:

create or replace procedure prc_get_dependencies(v_object_type varchar2,
                                                  v_object_name varchar2,
                                                  v_owner varchar2,
                                                  v_level number default 1)
is
  cursor c_get_dept
  is
  select type,name,owner
  from dba_dependencies
  where referenced_owner=v_owner and
        referenced_name=v_object_name and
        referenced_type=v_object_type;
begin
  dbms_output.put_line('|' || lpad(' ',v_level*5-5,' ') || v_object_type || '=>' || v_owner || '.' || v_object_name); 
  for rec_get_dept in c_get_dept
  loop
    prc_get_dependencies(rec_get_dept.type,rec_get_dept.name,rec_get_dept.owner,v_level+1);
  end loop;
end;
/

SQL> set serveroutput on
SQL> exec prc_get_dependencies('TABLE','EMPLOYEES','HR')
|TABLE=>HR.EMPLOYEES
|     VIEW=>HR.EMP_DETAILS_VIEW
|     TRIGGER=>HR.UPDATE_JOB_HISTORY
|     VIEW=>HR.V_AVSAL

PL/SQL procedure successfully completed.

Entsprechende Abänderung der Prozedur, für die Durchführung der abhängigen Kompilierung:

create or replace procedure prc_compile_dependencies(v_object_type varchar2,
                                                  v_object_name varchar2,
                                                  v_owner varchar2,
                                                  v_level number default 1)
is
  cursor c_get_dept
  is
  select type,name,owner
  from dba_dependencies
  where referenced_owner=v_owner and
        referenced_name=v_object_name and
        referenced_type=v_object_type;
  v_status_count number:=0;
  v_compiled varchar2(100);
begin
   
  select count(*)
  into v_status_count
  from dba_objects
  where owner=v_owner and object_name=v_object_name and 
        object_type=v_object_type and status='INVALID';
  
  if v_status_count>0 then
    begin
v_compiled:='COMPILATION SUCCESSFUL!';
case v_object_type
  when 'PROCEDURE' then
execute immediate 'alter procedure ' || v_owner || '.' || 
v_object_name || ' compile';
  when 'FUNCTION' then
execute immediate 'alter function ' || v_owner || '.' || 
v_object_name || ' compile';
  when 'PACKAGE' then
execute immediate 'alter package ' || v_owner || '.' || 
v_object_name || ' compile';
  when 'PACKAGE BODY' then
execute immediate 'alter package ' || v_owner || '.' || 
v_object_name || ' compile body';
  when 'TYPE' then
execute immediate 'alter type ' || v_owner || '.' || 
v_object_name || ' compile';
  when 'TYPE BODY' then
execute immediate 'alter type ' || v_owner || '.' || 
v_object_name || ' compile body';
  when 'VIEW' then
execute immediate 'alter view ' || v_owner || '.' || 
v_object_name || ' compile';
  when 'TRIGGER' then
execute immediate 'alter trigger ' || v_owner || '.' || 
v_object_name || ' compile';
  else
v_compiled:='COMPILATION FOR THIS OBJECT NOT SUPPORTED!';
    end case;
    exception
      when others
        then
          v_compiled:='COMPILATION FAILED!';
    end;
  else
    v_compiled:='NO COMPILATION NEEDED!';
  end if;
  dbms_output.put_line('|' || lpad(' ',v_level*5-5,' ') || v_object_type || '=>' || 
                       v_owner || '.' || v_object_name || '=>' || v_compiled);
  for rec_get_dept in c_get_dept
  loop
    prc_compile_dependencies(rec_get_dept.type,rec_get_dept.name,rec_get_dept.owner,v_level+1);
  end loop;
end;
/

SQL> exec prc_compile_dependencies('TABLE','JOB_HISTORY','HR')
|TABLE=>HR.JOB_HISTORY=>NO COMPILATION NEEDED!
|     PROCEDURE=>HR.ADD_JOB_HISTORY=>NO COMPILATION NEEDED!
|          TRIGGER=>HR.UPDATE_JOB_HISTORY=>NO COMPILATION NEEDED!

PL/SQL procedure successfully completed.

Erweiterung der Prozedur für die Überprüfung aller Objekte auf Ungültigkeit und Kompilierung der abhängigen Objekte, falls notwendig:

create or replace procedure prc_compile_schema(v_schema varchar2)
is
  cursor c_independent_objects(p_schema varchar2)
  is
  (select referenced_owner, referenced_type,referenced_name
  from dba_dependencies where referenced_owner=p_schema
  minus
  select owner,type,name from dba_dependencies)
  union
  (select owner, type,name from dba_dependencies
  where owner=p_schema
  minus
  select owner, type,name from dba_dependencies
  where owner=p_schema and referenced_owner=p_schema);
  
  
  procedure prc_compile_dependencies(v_object_type varchar2,
                                     v_object_name varchar2,
                                     v_owner varchar2,
                                     v_level number default 1)
  is
    cursor c_get_dept
    is
    select type,name,owner
    from dba_dependencies
    where referenced_owner=v_owner and
          referenced_name=v_object_name and
          referenced_type=v_object_type;
    v_status_count number:=0;
    v_compiled varchar2(100);
  begin
     
    select count(*)
    into v_status_count
    from dba_objects
    where owner=v_owner and object_name=v_object_name and 
object_type=v_object_type and status='INVALID';
    
    if v_status_count>0 then
      begin
  v_compiled:='COMPILATION SUCCESSFUL!';
      case v_object_type
        when 'PROCEDURE' then
          execute immediate 'alter procedure ' || v_owner || '.' || 
  v_object_name || ' compile';
        when 'FUNCTION' then
          execute immediate 'alter function ' || v_owner || '.' || 
  v_object_name || ' compile';
        when 'PACKAGE' then
          execute immediate 'alter package ' || v_owner || '.' || 
  v_object_name || ' compile';
        when 'PACKAGE BODY' then
          execute immediate 'alter package ' || v_owner || '.' || 
  v_object_name || ' compile body';
        when 'TYPE' then
          execute immediate 'alter type ' || v_owner || '.' || 
  v_object_name || ' compile';
        when 'TYPE BODY' then
          execute immediate 'alter type ' || v_owner || '.' || 
  v_object_name || ' compile body';
        when 'VIEW' then
          execute immediate 'alter view ' || v_owner || '.' || 
  v_object_name || ' compile';
        when 'TRIGGER' then
          execute immediate 'alter trigger ' || v_owner || '.' || 
  v_object_name || ' compile';
else
v_compiled:='COMPILATION FOR THIS OBJECT NOT SUPPORTED!';
      end case;
       v_compiled:='COMPILATION SUCCESSFUL!';
      exception
        when others
          then
            v_compiled:='COMPILATION FAILED!';
      end;
    else
      v_compiled:='NO COMPILATION NEEDED!';
    end if;
    dbms_output.put_line('|' || lpad(' ',v_level*5-5,' ') || v_object_type || '=>' || 
 v_owner || '.' || v_object_name || '=>' || v_compiled);
    for rec_get_dept in c_get_dept
    loop
      prc_compile_dependencies(rec_get_dept.type,
                           rec_get_dept.name,
   rec_get_dept.owner,
   v_level+1);
    end loop;
  end prc_compile_dependencies;
    
begin
  if v_schema='SYS'
  then
     raise_application_error(-20000,'Don''t use SYS for compilation!');
  end if;
  for rec_independent_objects in c_independent_objects(v_schema)
  loop
    prc_compile_dependencies(rec_independent_objects.referenced_type,
                         rec_independent_objects.referenced_name,
 rec_independent_objects.referenced_owner);
  end loop;
end;
/

SQL> exec prc_compile_schema('HR')
|PROCEDURE=>HR.PRC_COMPILE_DEPENDENCIES=>NO COMPILATION NEEDED!
|PROCEDURE=>HR.PRC_COMPILE_SCHEMA=>NO COMPILATION NEEDED!
|PROCEDURE=>HR.PRC_GET_DEPENDENCIES=>NO COMPILATION NEEDED!
|PROCEDURE=>HR.PRC_SHOW_DEPENDENCIES=>NO COMPILATION NEEDED!
|PROCEDURE=>HR.SECURE_DML=>NO COMPILATION NEEDED!
|TABLE=>HR.COUNTRIES=>NO COMPILATION NEEDED!
|     VIEW=>HR.EMP_DETAILS_VIEW=>NO COMPILATION NEEDED!
|TABLE=>HR.DEPARTMENTS=>NO COMPILATION NEEDED!
|     VIEW=>HR.EMP_DETAILS_VIEW=>NO COMPILATION NEEDED!
|TABLE=>HR.EMPLOYEES=>NO COMPILATION NEEDED!
|     VIEW=>HR.EMP_DETAILS_VIEW=>NO COMPILATION NEEDED!
|     TRIGGER=>HR.UPDATE_JOB_HISTORY=>NO COMPILATION NEEDED!
|     VIEW=>HR.V_AVSAL=>NO COMPILATION NEEDED!
|TABLE=>HR.JOBS=>NO COMPILATION NEEDED!
|     VIEW=>HR.EMP_DETAILS_VIEW=>NO COMPILATION NEEDED!
|TABLE=>HR.JOB_HISTORY=>NO COMPILATION NEEDED!
|     PROCEDURE=>HR.ADD_JOB_HISTORY=>NO COMPILATION NEEDED!
|          TRIGGER=>HR.UPDATE_JOB_HISTORY=>NO COMPILATION NEEDED!
|TABLE=>HR.LOCATIONS=>NO COMPILATION NEEDED!
|     VIEW=>HR.EMP_DETAILS_VIEW=>NO COMPILATION NEEDED!
|TABLE=>HR.REGIONS=>NO COMPILATION NEEDED!
|     VIEW=>HR.EMP_DETAILS_VIEW=>NO COMPILATION NEEDED!
|TYPE=>HR.TYPE_GRADES=>NO COMPILATION NEEDED!
|TYPE=>HR.TYPE_HIERARCHY=>NO COMPILATION NEEDED!
|     TYPE=>HR.TYPE_TAB_HIERARCHY=>NO COMPILATION NEEDED!
|TYPE=>HR.TYPE_TAB_DEPENDENT_OBJECT=>NO COMPILATION NEEDED!
|     FUNCTION=>HR.FNC_SHOW_DEPENDENCIES=>NO COMPILATION NEEDED!
|TYPE=>HR.TYP_CHAR=>NO COMPILATION NEEDED!
|     TYPE=>HR.TYP_TAB_CHAR=>NO COMPILATION NEEDED!
|TYPE=>HR.TYP_PERSON=>NO COMPILATION NEEDED!

PL/SQL procedure successfully completed.

Zur Anzeige der Abhängigkeiten der Objekte eines Schemas über eine Funktion kann die nachfolgende  Tabellenfunktion verwendet werden:

create or replace type type_tab_dependent_object
as table of varchar2(1000)
/

create or replace function fnc_show_dependencies(v_schema varchar2)
return type_tab_dependent_object
is
  cursor c_independent_objects(p_schema varchar2)
is
(select referenced_owner, referenced_type,referenced_name
from dba_dependencies where referenced_owner=p_schema
minus
select owner,type,name from dba_dependencies)
union
(select owner, type,name from dba_dependencies
where owner=p_schema
minus
select owner, type,name from dba_dependencies
where owner=p_schema and referenced_owner=p_schema);

tab_dependent_object type_tab_dependent_object:=type_tab_dependent_object();

procedure prc_get_dependencies(v_object_type varchar2,
   v_object_name varchar2,
   v_owner varchar2,
   v_level number default 1)
is
  cursor c_get_dept
  is
  select type,name,owner
  from dba_dependencies
  where referenced_owner=v_owner and
referenced_name=v_object_name and
referenced_type=v_object_type;

v_row varchar2(1000);

begin

  v_row:='|' || lpad(' ',v_level*5-5,' ') || v_object_type || '=>' || v_owner || '.' || v_object_name;
  tab_dependent_object.extend;
  tab_dependent_object(tab_dependent_object.count):=v_row;
  for rec_get_dept in c_get_dept
  loop
prc_get_dependencies(rec_get_dept.type,rec_get_dept.name,rec_get_dept.owner,v_level+1);
  end loop;
end prc_get_dependencies;
begin

  if v_schema='SYS'
  then
raise_application_error(-20000,'Don''t use SYS for selection!');
  end if;
 
  for rec_independent_objects in c_independent_objects(v_schema)
  loop
    prc_get_dependencies(rec_independent_objects.referenced_type,
                     rec_independent_objects.referenced_name,
 rec_independent_objects.referenced_owner);
  end loop;
  return tab_dependent_object;
end;
/

SQL> col column_value format a100 

SQL> set pagesize 10000
SQL> select * from table(fnc_show_dependencies('HR'));

COLUMN_VALUE
--------------------------------------------------------
|PROCEDURE=>HR.PRC_COMPILE_DEPENDENCIES
|PROCEDURE=>HR.PRC_COMPILE_SCHEMA
|PROCEDURE=>HR.PRC_GET_DEPENDENCIES
|PROCEDURE=>HR.PRC_SHOW_DEPENDENCIES
|PROCEDURE=>HR.SECURE_DML
|TABLE=>HR.COUNTRIES
|     VIEW=>HR.EMP_DETAILS_VIEW
|TABLE=>HR.DEPARTMENTS
|     VIEW=>HR.EMP_DETAILS_VIEW
|TABLE=>HR.EMPLOYEES
|     VIEW=>HR.EMP_DETAILS_VIEW
|     TRIGGER=>HR.UPDATE_JOB_HISTORY
|     VIEW=>HR.V_AVSAL
|TABLE=>HR.JOBS
|     VIEW=>HR.EMP_DETAILS_VIEW
|TABLE=>HR.JOB_HISTORY
|     PROCEDURE=>HR.ADD_JOB_HISTORY
|          TRIGGER=>HR.UPDATE_JOB_HISTORY
|TABLE=>HR.LOCATIONS
|     VIEW=>HR.EMP_DETAILS_VIEW
|TABLE=>HR.REGIONS
|     VIEW=>HR.EMP_DETAILS_VIEW
|TYPE=>HR.TYPE_GRADES
|TYPE=>HR.TYPE_HIERARCHY
|     TYPE=>HR.TYPE_TAB_HIERARCHY
|TYPE=>HR.TYPE_TAB_DEPENDENT_OBJECT
|     FUNCTION=>HR.FNC_SHOW_DEPENDENCIES
|TYPE=>HR.TYP_CHAR
|     TYPE=>HR.TYP_TAB_CHAR
|TYPE=>HR.TYP_PERSON

30 rows selected.

Vor Oracle 11g konnte die Ausführungsreihenfolge gleicher Trigger auf einer Tabelle nicht beeinflusst werden. Dieses kann ab Oracle 11g mit der FOLLOWS-Klausel erreicht werden.

CONN HR/hr
SET ECHO ON
SET SERVEROUTPUT ON
CL SCR

CREATE TABLE TAB_TEST
(
 S1 NUMBER,
 S2 VARCHAR2(10)
);

CREATE OR REPLACE TRIGGER TR_1
BEFORE INSERT ON TAB_TEST
FOR EACH ROW
BEGIN
 DBMS_OUTPUT.PUT_LINE('TR_1');
END;
/

CREATE OR REPLACE TRIGGER TR_2
BEFORE INSERT ON TAB_TEST
FOR EACH ROW
BEGIN
 DBMS_OUTPUT.PUT_LINE('TR_2');
END;
/
PAUSE

SET ECHO OFF
EXEC DBMS_OUTPUT.PUT_LINE('INSERTING DATA');
INSERT INTO TAB_TEST VALUES(1,'TEST');
EXEC DBMS_OUTPUT.PUT_LINE('-----');
INSERT INTO TAB_TEST VALUES(1,'TEST');

PAUSE

DROP TABLE TAB_TEST PURGE;

SET ECHO ON

CREATE TABLE TAB_TEST
(
 S1 NUMBER,
 S2 VARCHAR2(10)
);

CREATE OR REPLACE TRIGGER TR_1
BEFORE INSERT ON TAB_TEST
FOR EACH ROW
BEGIN
 DBMS_OUTPUT.PUT_LINE('TR_1');
END;
/

CREATE OR REPLACE TRIGGER TR_2
BEFORE INSERT ON TAB_TEST
FOR EACH ROW
FOLLOWS TR_1
BEGIN
 DBMS_OUTPUT.PUT_LINE('TR_2');
END;
/

PAUSE

SET ECHO OFF
EXEC DBMS_OUTPUT.PUT_LINE('INSERTING DATA');
INSERT INTO TAB_TEST VALUES(1,'TEST');
EXEC DBMS_OUTPUT.PUT_LINE('-----');
INSERT INTO TAB_TEST VALUES(1,'TEST');

PAUSE

DROP TABLE TAB_TEST PURGE;

SET ECHO ON

Compound Trigger in Oracle 11g zur Vermeidung von mutierenden Triggern.

Das folgende Beispiel zeigt einen mutierenden Trigger. Mutierende Trigger entstehen, wenn ein ROW-Trigger auf die Tabelle Abfragen oder Änderungen durchführt, auf die er gelegt wurde. Die Ursache, dass die Ausführung dieses Triggers fehlschlägt liegt darin begründet, dass er bei DML-Anweisungen, die mehrere Zeilen in der Tabelle ändern, für jede Zeilenänderung ausgeführt wird. Somit greift der Trigger in eine laufende Änderungsaktion ein und erhält somit eine inkonsistente Sicht auf die Daten.


CONN HR/hr

SET ECHO ON
SET SERVEROUTPUT ON
CL SCR

SET ECHO ON

CREATE OR REPLACE TRIGGER TR_SAL_CHECK
BEFORE INSERT OR UPDATE
ON EMPLOYEES
FOR EACH ROW
DECLARE
 HIGH_SAL EMPLOYEES.SALARY%TYPE;
 LOW_SAL EMPLOYEES.SALARY%TYPE;
BEGIN
 SELECT MAX(SALARY),MIN(SALARY)
 INTO HIGH_SAL, LOW_SAL
 FROM EMPLOYEES;
 IF :NEW.SALARY NOT BETWEEN LOW_SAL AND HIGH_SAL
 THEN
  RAISE_APPLICATION_ERROR(-20000,'GEHALT ZU HOCH ODER ZU NIEDRIG');
 END IF;
END;
/

PAUSE

UPDATE EMPLOYEES SET SALARY=SALARY*1.1 WHERE EMPLOYEE_ID=100;

UPDATE EMPLOYEES SET SALARY=SALARY*1.1 WHERE EMPLOYEE_ID=100       
* ERROR at line 1: ORA-04091: table HR.EMPLOYEES is mutating, trigger/function may not see it
ORA-06512: at "HR.TR_SAL_CHECK", line 5
ORA-04088: error during execution of trigger 'HR.TR_SAL_CHECK'

PAUSE

DROP TRIGGER TR_SAL_CHECK;

Um dieses Problem zu lösen, wurde der Compound-Trigger eingeführt, der eine Zusammensetzung aller DML-Triggerarten ermöglicht. Hierbei kann ein Compound-Trigger eine Zusammensetzung aus Before-Statemant, Before-Row, After-Row und After-Statement sein.

Die Ausführungsreihenfolge der Triggerteile wäre dann:

  1. Einmalig der Before-Statement Teil
  2. Für jede Zeile erst der Before-Row und dann der After-Row Teil
  3. Einmalig der After-Statement Teil

Da ein Compound-Trigger einen globalen Deklarationsbereich besitzt, können hier Variablen definiert werden, die von allen Triggerteilen verwendet werden können. Da ein mutierender Trigger nicht bei Statement-Triggern auftaucht, weil er entweder vor oder am Ende der Anweisung ausgeführt wird, können diese Teile verwendet werden, um globale Variablen zu füllen, deren Werte dann an den Row-Trigger-Bereich weitergeleitet werden.

Die Lösung des im ersten Beispiel entstandenen Problems liegt in der Verwendung eines Compound Triggers:

CONN HR/hr
SET ECHO ON
SET SERVEROUTPUT ON
CL SCR

SET ECHO ON

CREATE OR REPLACE TRIGGER TR_SAL_CHECK
FOR INSERT OR UPDATE
ON EMPLOYEES
COMPOUND TRIGGER
  -- Global declaration.
  HIGH_SAL EMPLOYEES.SALARY%TYPE;
  LOW_SAL EMPLOYEES.SALARY%TYPE;

  BEFORE STATEMENT IS
  BEGIN
    SELECT MAX(SALARY),MIN(SALARY)
 INTO HIGH_SAL, LOW_SAL
 FROM EMPLOYEES;
  END BEFORE STATEMENT;

  BEFORE EACH ROW IS
  BEGIN
    IF :NEW.SALARY NOT BETWEEN LOW_SAL AND HIGH_SAL
 THEN
  RAISE_APPLICATION_ERROR(-20000,'GEHALT ZU HOCH ODER ZU NIEDRIG');
 END IF;
  END BEFORE EACH ROW;
END TR_SAL_CHECK;
/

PAUSE

UPDATE EMPLOYEES SET SALARY=SALARY*1.1 WHERE EMPLOYEE_ID=100;

UPDATE EMPLOYEES SET SALARY=SALARY*1.1 WHERE EMPLOYEE_ID=100       
* ERROR at line 1: ORA-20000: GEHALT ZU HOCH ODER ZU NIEDRIG
ORA-06512: at "HR.TR_SAL_CHECK", line 17
ORA-04088: error during execution of trigger 'HR.TR_SAL_CHECK'

PAUSE

DROP TRIGGER TR_SAL_CHECK;

Funktion zum Testen der nativen Kompilierung unter Oracle 11g.

CONN / AS SYSDBA
SET ECHO ON
SET SERVEROUTPUT ON
CL SCR

ALTER SESSION SET PLSQL_CODE_TYPE=INTERPRETED;

PAUSE

CREATE OR REPLACE PROCEDURE NATIVE_TEST_PROC(V_COMPTYPE VARCHAR2) AS
  L_START               NUMBER;
  L_LOOPS               NUMBER := 10000000;
  L_PLS_INTEGER         PLS_INTEGER := 0;
  L_PLS_INTEGER_INCR    PLS_INTEGER := 1;
BEGIN
  L_START := DBMS_UTILITY.GET_TIME;
  FOR I IN 1 .. L_LOOPS LOOP
    L_PLS_INTEGER := L_PLS_INTEGER + L_PLS_INTEGER_INCR;
  END LOOP;
  DBMS_OUTPUT.PUT_LINE(V_COMPTYPE || ': ' || (DBMS_UTILITY.GET_TIME - L_START) || ' HSECS');
END;
/

PAUSE

EXEC NATIVE_TEST_PROC('INTERPRETED')

PAUSE

ALTER SESSION SET PLSQL_CODE_TYPE=NATIVE;

PAUSE

ALTER PROCEDURE NATIVE_TEST_PROC COMPILE;

PAUSE

EXEC NATIVE_TEST_PROC('NATIVE')

PAUSE

DROP PROCEDURE NATIVE_TEST_PROC;

RMAN verwendet zur Durchführung von Sicherungen das nicht dokumentierte Package DBMS_BACKUP_RESTORE. Hierzu ein kleines Beispiel. RMAN verwendet zur Durchführung von Sicherungen das nicht dokumentierte Package DBMS_BACKUP_RESTORE. Hierzu ein Beispiel für eine komprimierte Sicherung der gesamten Datenbank in die Flashrecovery Area. Diese Art der Sicherung wird von Oracle nicht unterstützt und dient nur zu Demonstrationszwecken. 


declare
   v_device varchar(4000);
   v_set_stamp number;
   v_set_count number;
   v_pieceno  binary_integer;
   v_done     boolean;
   v_handle   varchar2(4000);
   v_comment  varchar2(4000);
   v_media    varchar2(4000);
   v_concur   boolean:=FALSE;
   v_archlog_failover boolean:=false;
   v_deffmt binary_integer:=1; --Flash Recovery Area
   v_recid number;
   v_stamp number;
   v_tag varchar2(100);
   v_docompress boolean:=true;
   v_counter number:=0;
   cursor c_datafiles is select file# from v$datafile;
begin
   sys.dbms_backup_restore.backupSetDataFile(set_stamp=>v_set_stamp,set_count=>v_set_count);
   v_device:=sys.dbms_backup_restore.deviceAllocate;
   for rec_datafiles in c_datafiles loop
           sys.dbms_backup_restore.backupDataFile(rec_datafiles.file#);
   end loop;

   sys.dbms_backup_restore.backupPieceCreate( fname=>' ',
            pieceno=>v_pieceno,
            done=>v_done,
            handle=>v_handle,
            comment=>v_comment,
            media=>v_media,
            concur=>v_concur,
            archlog_failover=>v_archlog_failover,
            deffmt=>v_deffmt,
            recid=>v_recid,
            stamp=>v_stamp,
            tag=>v_tag,
            docompress=>v_docompress
            );
   sys.dbms_backup_restore.deviceDeallocate();
   sys.dbms_backup_restore.backupCancel;
end;
/