In Vorbereitung für unseren neuen zweitägigen Kurs Oracle auf Postgres Migration, den wir ab Juli 2021 anbieten werden, ist mir aufgefallen, dass es weltweit wenige Beispiele zu Postgres utl_file Implementierung gibt.
Zeit, das jetzt und hier nachzuholen ...:-)
Vorbereitungen:
Das "Package" (Postgres hat eigentlich gar keine Packages) utl_file ist leider nicht im Standardumfang einer Postgres Installation enthalten, man benötigt dazu die Extension ORAFCE,
für das bereits viele Installationsanleitungen und eine gute Doku gibt.
Nachdem also erfolgreich der nachfolgende Befehl (nach der Installation aller notwendigen Packages in Linux) in psql oder pgadmin ausgeführt wurde, können wir loslegen...
CREATE EXTENSOPN ORAFCE
Wir brauchen ein Verzeichnis mit dem wir arbeiten möchten. In unserem Beispiel verwenden wir das Verzeichnis /tmp. Dieses Arbeits-Verzeichnis tragen wir in eine Tabelle ein:
Hinweis: Postgres hat keinen Directory Typ
INSERT INTO utl_file.utl_file_dir values ('/tmp','tmp');
Einfaches Beispiel (eine Zeile wird geschrieben):
CREATE OR REPLACE PROCEDURE write_file(
mydir TEXT DEFAULT '/tmp',
outfile TEXT DEFAULT 'outfile.txt') AS $$
DECLARE
otf UTL_FILE.FILE_TYPE;
BEGIN
otf := UTL_FILE.FOPEN(mydir, outfile,'w');
PERFORM UTL_FILE.PUT_LINE(otf,'Test:'||now(),TRUE);
otf := UTL_FILE.FCLOSE(otf);
END; $$ LANGUAGE plpgsql;
call write_file('/tmp','x.x');
\! cat /tmp/x.x
Tabelle in Datei schreiben
CREATE OR REPLACE PROCEDURE write_tab(
mydir TEXT DEFAULT '/tmp',
outfile TEXT DEFAULT 'file.txt') AS $$
DECLARE
f UTL_FILE.FILE_TYPE;
emp_curs CURSOR IS SELECT * FROM scott.emp;
tz VARCHAR2(10):=';';
BEGIN
f := UTL_FILE.FOPEN(mydir, outfile,'w');
FOR c IN emp_curs LOOP
PERFORM UTL_FILE.PUT_LINE(f,
c.empno||tz||c.ename||tz||c.job||tz||c.hiredate||tz||c.sal||tz||coalesce(c.comm::varchar2,'')||tz||c.deptno,TRUE);
END LOOP;
f := UTL_FILE.FCLOSE(f);
END; $$ LANGUAGE plpgsql;
call write_tab('/tmp','emp.txt');
\! cat /tmp/emp.txt
Daten aus Datei lesen
CREATE OR REPLACE PROCEDURE read_file(
mydir TEXT DEFAULT '/tmp',
infile TEXT DEFAULT 'file.txt') AS $$
DECLARE
f UTL_FILE.FILE_TYPE;
v_text VARCHAR(32767);
BEGIN
f := UTL_FILE.FOPEN(mydir, infile,'r');
LOOP
BEGIN
v_text := UTL_FILE.GET_LINE(f,256);
RAISE NOTICE '%',v_text;
EXCEPTION WHEN no_data_found THEN
EXIT;
END;
END LOOP;
f := UTL_FILE.FCLOSE(f);
END; $$ LANGUAGE plpgsql;
call read_file('/tmp','emp.txt');