1. Februar 2010

PL/SQL-gesteuerte Import-Operationen mit der Data Pump

English title: Import operations using PL/SQL and DBMS_DATAPUMP

Im letzten Blog Posting hatte ich die Möglichkeit vorgestellt, Export-Vorgänge mit dem Paket DBMS_DATAPUMP aus PL/SQL heraus zu starten. Heute zeige ich ein analoges Beispiel für den Import. Voraussetzung ist, dass die Export-Datei schon vorhanden ist. Es muss eine Data Pump(!) Exportdatei sein, mit "klassischen" Dumpfiles wird die heute vorgestellte Prozedur nicht funktionieren.
In the previous blog posting I showed how to initiate an export operation with PL/SQL code using the PL/SQL package DBMS_DATAPUMP. In this posting I'll show how to perform the corresponding import operation. A prerequisite for today a an existing data pump(!) export dumpfile. This procedure will not work with "classic" export dumpfiles.
Wie beim letzten Mal muss ein Directory-Objekt vorhanden sein - die Data Pump arbeitet ja serverseitig.
As in the previous blog posting you need a directory object. Data Pump works at the server side.
create directory dp_test_dir as '/home/oracle'
/
Dann kommt die PL/SQL-Prozedur, die den Dump mit Hilfe von DBMS_DATAPUMP importiert. Als Parameter geben wir den Dateinamen und die zu importierende Tabelle an. Wenn das Dumpfile mehr als diese Tabelle enthält, wird trotzdem nur die angegebene Tabelle importiert. Wichtig hier ist der Abschnitt, in dem die TABLE_EXISTS_ACTION festgelegt wird: Wir geben hier an, dass die Zeilen dann hinzugefügt (APPEND) werden sollen. Andere Varianten wären SKIP oder REPLACE.
The next step is the PL/SQL procedure which imports the dumpfile using DBMS_DATAPUMP. The procedure expects the filename as well as the name of the table to be imported as its parameters. Only the specified tables are being imported. The section where the TABLE_EXISTS_ACTION is being specified is interesting. This determined what the data pump API should do if the table to be imported is already there. We choose APPEND in this case - which means that the rows in the import dumpfile are being appended to the table. Other options would be SKIP or REPLACE.
create or replace procedure import_file(
  p_file_name in varchar2,
  p_table_name in varchar2
)
is
  v_dp_handle number;
  pragma AUTONOMOUS_TRANSACTION; 
begin
    -- Create Data Pump Handle - "TABLE IMPORT" in this case
    v_dp_handle := dbms_datapump.open(
      operation      => 'IMPORT',
      job_mode       => 'TABLE'
    );
    
  -- Specify target file - %U adds a unique number to the file name
  dbms_datapump.add_file(
    handle         => v_dp_handle,
    filename       => p_file_name,
    directory      => 'DP_TEST_DIR'
  );

  -- Export only those tables specified in the procedure's parameter
  dbms_datapump.metadata_filter(
    handle         => v_dp_handle,
    name           => 'NAME_LIST',
    value          => p_table_name
  );

  -- IMPORTANT: Specify the "table exists" action. In our case the 
  -- rows should be appended to the existing ones. Other action types
  -- would be "REPLACE" or "SKIP"
  dbms_datapump.set_parameter(
    handle         => v_dp_handle,
    name           => 'TABLE_EXISTS_ACTION',
    value          => 'APPEND'
  );

  -- Do it!
  dbms_datapump.start_job(
    handle        => v_dp_handle
  );
  commit;
end;
/
sho err
Wichtig ist wieder das COMMIT am Ende (wegen der autonomen Transaktion, welche DBMS_DATAPUMP erwartet). Dann testen wir mal ...
The COMMIT at the end is important (as well as with the export operation). This is due to the autonomous transaction which DBMS_DATAPUMP requires. Let's try ...
SQL> select * from emp
              *
FEHLER in Zeile 1:
ORA-00942: Tabelle oder View nicht vorhanden

SQL> exec IMPORT_FILE('EMP_20100105-043120.dmp','EMP');

PL/SQL procedure successfully completed.

SQL> select * from emp;

EMPNO ENAME      JOB         MGR HIREDATE   SAL  COMM DEPTNO
----- ---------- --------- ----- -------- ----- ----- ------
 7369 SMITH      CLERK      7902 17.12.80   800           20
 7499 ALLEN      SALESMAN   7698 20.02.81  1600   300     30
 7521 WARD       SALESMAN   7698 22.02.81  1250   500     30
    : :          :             : :            :     :      :

14 rows selected.

SQL> exec IMPORT_FILE('EMP_20100105-043120.dmp','EMP');

PL/SQL procedure successfully completed.

SQL> select * from emp;

EMPNO ENAME      JOB         MGR HIREDATE   SAL  COMM DEPTNO
----- ---------- --------- ----- -------- ----- ----- ------
 7369 SMITH      CLERK      7902 17.12.80   800           20
 7499 ALLEN      SALESMAN   7698 20.02.81  1600   300     30
 7521 WARD       SALESMAN   7698 22.02.81  1250   500     30
    : :          :             : :            :     :      :

28 rows selected.
Auch hier ergeben sich interessante Möglichkeiten: Dumpfiles können nun (bspw. mit APEX) eingespielt werden, ohne dass man Betriebssystem-Zugriff auf den Datenbankserver benötigt. Man müsste nur das Dumpfile über eine Web-Applikation hochladen - den BLOB dann mit UTL_FILE in das Verzeichnis schreiben und mit DBMS_DATAPUMP dann einspielen. Die Data Pump erlaubt hier wesentlich flexiblere Möglichkeiten als das "alte" Export/Import. DBMS_DATAPUMP bietet noch zahlreiche Möglichkeiten, den Vorgang zu parametrisieren: So können neben Schemanamen auch Storage-Informationen beim Import angepasst werden. Ein altes Problem beim "klassischen" Export/Import war, wenn die Tabellen auf dem Zielsystem in einem anderen Tablespace liegen sollten. Das geht bei der Data Pump mit REMAP_TABLESPACE ganz einfach.
With this approach dumpfile can be imported using a Web GUI (say: APEX). The file could be uploaded via a browser - the BLOB needs then to be written to the file system with UTL_FILE and finally the import process can be triggered with DBMS_DATAPUMP. Operating system access to the database server is no longer necessary. Data Pump offers beyond this much more flexibility than the "classic" export/import: There are several options to parametrize the process. For instance: An "old" and well known problem of "classic" export/import is that the tablespace for a table changes in the target system. Data Pump handles this very smoothly with REMAP_TABLESPACE.
Viel Spaß damit!
Have fun!

Keine Kommentare:

Beliebte Postings