Datei erstellen/schreiben

Hallo zusammen,

Kann man mit pl/pgsql eine Datei erstellen/schreiben (OS-Ebenen wie UTL_FILE Package von Oracle)?

Wenn nicht…Könnte man 3 pl/perlu Funktionene open_file, put_line und close_file schreiben um dieses Problem anzugehen?

Aus einer pl/pgsql Funktion müsst zunächst open_file aufgerufen werden (returniert FileHandle…fragt sich nur, ob dieser Datentyp in pl/pgsql unterstützt wird). Danach kann man aus der pl/pgsql Funktion heraus die pl/perlu Funktion put_line aufrufen (FileHandle übergeben).

Was meint ihr dazu?

Gruss Bobby

Nein.

Wenn nicht…Könnte man 3 pl/perlu Funktionene open_file, put_line und close_file schreiben um dieses Problem anzugehen?

Ja.

Du wirst das aber nicht weiter in pl/pgsql nutzen können.


Andreas

Danke für die Antwort.

Aus welchem Grund?

Wie kann man dieses Problem lösen? Es muss doch eine Lösung dafür geben, nicht?

pl/pgsql ist eine ‘trusted language’.

Wie kann man dieses Problem lösen? Es muss doch eine Lösung dafür geben, nicht?

Mit einer ‘untrusted language’ arbeiten.

Andreas

Vielen Dank für prompte Antwort.

Ok.

Wir werde sehr wahrscheinlich eine Menge Funktionene schreiben müssen, welche Logfiles/Datenfiles generieren müssen. Wohrscheinlich müsste ich dann daher eher auf pl/pgsql verzichten und stattdessen eine andere prozedurale Sprache verwenden.

Gibst es gegenüber pl/pgsql Performance-Einbussen? Welche wäre voll besser pl/perl oder pl/php?

Wenn ich mich nicht täusche können aus pl/perl und pl/php Funktionen keine weiteren pl/pert bzw. pl/php Funktionene aufgerufen werden, stimmt das? Oje…

ASCII?

Machbar ist vieles, ich generiere mit pl/pgsql z.B. auch LaTeX-Files. Dazu habe ich eine Funktion in pl/pgsql, die erst einmal nur als return TEXT zurückgibt. Diese rufe ich via plsh auf und speichere das in einer Datei und rufe dann in plsh noch latex bzw. pdflatex auf und drucke es z.B.

Ein anderer Lösungsansatz wäre, mit LISTEN/NOTIFY zu arbeiten.

Gibst es gegenüber pl/pgsql Performance-Einbussen? Welche wäre voll besser pl/perl oder pl/php?

Um Files zu erstellen? Keine, sind beides ‘trusted’. Nur wenn ein ‘u’ dranhängt, kann man ihnen nicht trauen.


Andreas

Ja ASCII. Ich möchte auf einem Linux-Server zwei Verzeichnisse erstellen…/log und /data. In diese Verzeichnisse schreiben Batchprozesse (Function prozedurale Sprache) ihre Log- und Datenfiles während der Verarbeitung.

So wie es aussieht wird es mit pl/pgsql nicht wirklich funktionieren.

Es kommt daher fast nur pl/perlu in Frage.

Entschuldige bitte meine Unwissenheit, ich befasse mich erst seit kurzem mit Postgresql.

Für was benötigst Du denn später diese Dateien?

Zum loggen böte sich doch vielleicht auch gleich eine Tabelle an, mit z.B. timestamptz-Spalte und den zu loggenden Informationen.

Für was werden die Datendateien benötigt? Wenn Du die als Datei benötigst, dann wohl für eine externe Verarbeitung.
Du kannst ja auch psql mit -c ‘function()’ aufrufen und das in Datei schreiben, dazu muß Deine Funktion nur die Daten als RETURN zurückgeben (und psql mit -t und -q aufrufen)


Andreas

Ich möchte die nächtlichen Batchverarbeitungen über einen Job Scheduler anmelden können. Am nächsten Morgen werden die Logdateien durch das Consulting überprüft. Die Datendateien enthalten beispielsweise Adressinformationen (1 Eintrag eine Zeile…Name concat Vorname concat Strasse concat…). Es kann gut sein, dass bis 10 Mio. Zeilen herausgeschrieben werden. Natürlich werden diese Daten nicht auf einmal in das File geschrieben ( Loop Vearbeitung… Output schreiben… Verarbeitung). Deshalb sollte ich eben die Dateien während der Vearbeitung schreiben können und nicht erst als Return-Wert ausgeben. Es kann gut sein, dass eine Datendatei 500-1000 MB gross wird.

Ist dieser Vorgehen so ungewöhnlich? Ich verstehe nicht, dass meine Fragen nicht schon durch andere Benutzer gestellt wurden.

Könnte ich denn nicht mit pl/perlu arbeiten? Job Scheduler ruft die Batchverarbeigung auf (Function in pl/perlu)?

Ein Nachteil ist jedoch, dass pl/perlu Funktionene keine anderen pl/perlu aufrufen können, ist das korrekt? (Modulare Programmierung geht flöten…)

Nein.

Du sprichst von einem ‘Job Scheduler’ und meinst damit sicherlich CRON. Also willst Du offensichtlich von außen in der DB etwas anstoßen (Batchverarbeitung). Die DB kann das doch machen, intern. Und wenn Du da viele einzelne Datensätze durch eine Funktion erzeugst (deine bis 10 Mio. Zeilen), dann kannst Du diese auch in einer Tabelle speichern oder die Funktion als ‘SET RETURNING FUNCTION’ schreiben und diese Funktion von außen aufrufen und das Resultat (RETURN NEXT) der Funktion in eine Datei schreiben.

Außerdem:
Du sprichst von 10 Mio Zeilen und willst während der Verarbeitung schon die bisher verarbeiteten Daten sehen. Sind die 8 Millionen Daten gültig, die schon ausgegeben wurden, wenn der 8 Millionste +1 Datensatz einen Fehler verursacht?



Andreas

Ok. Ich weiss nicht, ob ich alles richtig verstanden habe…

Du würdest aber nur pl/pgsql verwenden ? Wo genau und wie würdest du dann die Datendatei erstellen? Ich will die Daten der Datendatei nicht in der DB speichern, weil ich diese nicht brauche…ich brauche sie lediglich als Output in einer Datei.

Während der Verarbeitung will ich zum Beispiel für jede 10000 geschriebene Zeile einen Eintrag in dieLogdatei vornehmen können, um den aktuellen Stand der Verarbeitung auszugeben.

Wäre dieses Vorgehen so ungewöhnlich…

Job Scheduler
Batch (Function pl/perlu)
Logdatei erstellen
Datendatei erstellen
Loop
Eintrag in Logdatei schreiben
Aufruf Function pl/pgsql (für Selects, Inserts, Updates)
Output in Datendatei
Vearbeitung…
End Loop…



Ich hoffe, ich mache dier nicht zu viele Umstände mit meiner Fragerei… :frowning:

Ok. Ich weiss nicht, ob ich alles richtig verstanden habe…

Du würdest aber nur pl/pgsql verwenden ? Wo genau und wie würdest du dann die Datendatei erstellen? Ich will die Daten der Datendatei nicht in der DB speichern, weil ich diese nicht brauche…ich brauche sie lediglich als Output in einer Datei.

Während der Verarbeitung will ich zum Beispiel für jede 10000 geschriebene Zeile einen Eintrag in dieLogdatei vornehmen können, um den aktuellen Stand der Verarbeitung auszugeben.

Wäre dieses Vorgehen so ungewöhnlich…

Job Scheduler
Begin Batch (Function pl/perlu)
Logdatei erstellen
Datendatei erstellen
Loop
Eintrag in Logdatei schreiben
Aufruf Function pl/pgsql (für Selects, Inserts, Updates)
Output in Datendatei
Vearbeitung…
End Loop…

Ende Batch (Funtion pl/perlu)


Ich hoffe, ich mache dier nicht zu viele Umstände mit meiner Fragerei… :frowning:

Okay. Simples, blödes Beispiel:

[php]
create or replace function simple_job(IN i int, OUT t text) returns setof TEXT as $$
declare rec record;
begin
for rec in select generate_series(0,1000) as c loop
t := 'Zeile ’ || rec.c::text;
if rec.c%100 = 0 then
insert into log1 (log) values (t);
end if;
return next;
end loop;
end;
$$language plpgsql;
[/php]

Das rufe ich nun so auf, von der Shell aus, könnte auch per CRON erfolgen:

kretschmer@pegasus:~$ psql -U webmaster test -c 'select * from simple_job(2)' > simple_job.data
kretschmer@pegasus:~$ psql -U webmaster test -c 'select * from log1' > simple_job.log

Ich habe nun 2 Dateien, in der einen die Daten, in der anderen das Log:

kretschmer@pegasus:~$ head -10 simple_job.data
     t
------------
 Zeile 0
 Zeile 1
 Zeile 2
 Zeile 3
 Zeile 4
 Zeile 5
 Zeile 6
 Zeile 7
kretschmer@pegasus:~$ head -10 simple_job.log
              ts               |    log
-------------------------------+------------
 2008-01-11 14:19:10.964582+01 | Zeile 0
 2008-01-11 14:19:10.96543+01  | Zeile 100
 2008-01-11 14:19:10.966064+01 | Zeile 200
 2008-01-11 14:19:10.966675+01 | Zeile 300
 2008-01-11 14:19:10.967287+01 | Zeile 400
 2008-01-11 14:19:10.967908+01 | Zeile 500
 2008-01-11 14:19:10.968575+01 | Zeile 600
 2008-01-11 14:19:10.969191+01 | Zeile 700

Andreas

Ok, vielen Dank für das Beispiel Andreas.

Ich nehme nicht an, dass man 2 returns setof Konstrukte mit RETURN NEXT zurückgeben kann…So könnte man sich die Tabelle log1 noch sparen.

Du würdest ganz klar diese Variante meiner vorziehen. Ich nehme an die Vorteile liegen darin, dass man nicht pl/perlu einsetzen muss.

Ja.

Du würdest ganz klar diese Variante meiner vorziehen. Ich nehme an die Vorteile liegen darin, dass man nicht pl/perlu einsetzen muss.

Das zum einen, zum anderen wolltest Du ja pl/pgsql verwenden.

Andreas

OK.

Nun meine letzte Frage…Wie würdest du dann eine ASCII-File einlesen ? Genau das gleiche Szenario, nur dieses Mal wird ein File eingelesen und gemäss den Angaben im File die Verarbeitung durchgeführt (inserts, updates…)

Ich möchte jmich etzt schon für deine grosszügige Hilfe und Geduld bedanken.

Gruss Bobby

In der Datei stehen SQL-Befehle? Dann mit psql -f …

Andreas

Nein keine SQL-Befehle. Es besteht zum Beispiel aus 20000 Zeilen (ID concat Personenstatus concat name concat vorname…)

Ich muss diese Daten einlesen und dann Zeile für abarbeiten und daraus die nötigen inserts/updates auslösen.

Wenn da praktikable Trennzeichen zwischen den Feldern sind böte sich COPY an, das ist Lichtjahre schneller als INSERT. Falls Datensätze upzudaten sind, böte sich u.U. auch erst einmal ein COPY in eine Zwischentabelle an, mit der man dann mit regulärem SQL arbeitet.

Andreas

Ok, danke für die Hilfe.

Bis bald :slight_smile:

Gruss Bobby