PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Postgres Programmierung



wackeldackel
20-01-2005, 21:03
Guten Abend,

ich habe ein kleines Problem mit meinem Wissensstand.
Möchte folgendes bewerkstelligen.

Schicke per FTP eine Datei (Lieferschein) an einen Server. Dieser wird per Skript und cronjob in insertbefehle umgewandelt und in die Datenbank eingelesen. Soweit funktioniert auch alles.

Jetzt kommt der Knackpunkt.

Per Funktion (on insert) sollen die neu eingelesenen Lieferscheindaten auf die entsprechenden Tabellen verteilt werden. (Artikel, Artikelbestand, Artikelfarbe, usw.) Dabei kann es sein, dass der Artikel bereits vorhanden ist und dann die Datensätze nur upgedated werden sollen.

Das funktioniert ja nur über eine postgresinterne Programmierung !?!?!
(automatisch meine ich)
Gibt es hier irgendwelche empfehlenswerte Literatur (Habe von Addison Wesley das Postgres Buch und hier wird nur am Rande darauf eingegangen.)

elrond
21-01-2005, 07:48
hallo wackeldackel,

soweit ich die Doku verstanden habe, kann postgres mit unterschiedlichen Sprachen umgehen. Damit ist die Aufgabe, die Du stellst sicherlich zu bewerkstelligen.

Ich habe mich aus verschiedenen Gründen gegen diesen Weg entschieden, und setzte statt dessen Perl (extern) ein, um Aktionen mmwie Importe, Exporte usw vorzunehmen.
Der Zugriff mit Perl via DBI funktioniert absolut problemlos und performant.

Ein Grund solche Dinge nicht DB-intern zu machen, ist die Datenbankabhängigkeit, in die man sich mit einer solchen Entwicklung begibt. Bei uns in der Firma ist vor ein paar Jahren eine solche Entwicklung für interne Sachen auf dem MS-SQL-Server "gewachsen". Das System ist faktisch nicht migrierbar, auch wenn es gute preiswerte Alternativen wie z.B. postgres gibt.

Ähnliches könnte Dir auch passieren, wenn Du die DB-Plattform wechselst... :cool:

Christoph
21-01-2005, 10:25
Ich würde Dir auch empfehlen das nicht mit stored Procedures, sondern mit einem kleinen seperaten Programm zu lösen. Programmierschnittstellen bietet PostgreSQL viele: C, Perl (DBI), Python, ...

Kurioserweise habe ich Deine Aufgabenstellung vor einiger Zeit bei uns im Datenbankpraktikum gestellt, allerdings mit einer zusätzlichen Anforderung, dabei selber ein simples abstraktes Interface zu schreiben:
http://lionel.kr.hs-niederrhein.de/~dalitz/data/lehre/DBS/aufgabe3.pdf

Hans-Georg Normann
21-01-2005, 17:34
Ich finde die Idee mit den Stored Procedures garnicht einmal so schlecht. Kommt allerdings auch auf den Inhalt der Datei an. Vielleicht kann man das ganze ja etwas weiter aufbereiten, so dass man die Daten leichter integrieren kann.

Ich würde es wahrscheinlich so lösen.

Kopfdaten auslesen und in eine eigene Datei schreiben
Positionsdaten auslesen und in eine separate Datei schreiben
Kopfdaten in eine Tabelle KJOUERNAL schreiben
Positionsdaten in eine Tabelle PJOURNAL schreiben
Bestandsdateien per AfterUpdate oder wie immer das Event der PJOURNAL heißt updaten.
ggfs. die Original Lieferscheindatei archivieren.
Dafür muß man nichteinmal Perl & Co. bemühen. AWK sollte ausreichen, ist aber Geschmackssache.

Kannst du nicht einmal so einen Musterlieferschein posten oder attachen?

Hans

wackeldackel
22-01-2005, 16:07
Danke für die Tipps,

also die Lieferscheine sehen so aus:
ID;Artikelnummer;ArtikelID;Bezeichnung;Lieferant;H ersteller;Farbe;Groesse;PreisDM;PreisEuro;Menge
161104_2;4030563095065;K3;Krawatten;4030563;Hatico ;18;1;0;14.9;1
161104_2;4030563217900;K2;Krawatten;4030563;Hatico ;19;1;0;19.9;100
161104_2;4030563094884;K1;Krawatten;4030563;Hatico ;17;1;0;9.9;50

ohne Kopfzeile !!!, die ist nur für das bessere Verständnis. Naja ich würde die Sache noch um ein paar Spalten erweitern (MwSt, Umsatzgruppe,...)

Was die Abhängigkeit von der DB angeht, so ist da kein Problem. Das ist ein privates Projekt für geschäftlichen Einsatz. Sozusagen mein Zeitvertreib, der wenn er funktioniert, verwendet wird, oder nicht. Somit bestimme ich die Regeln und wir setzen im Unternehmen die Postgres DB eh schon ein.

An eine externe Aufbereitung hatte ich auch schon gedacht. Per Cronjob "einfach" die benötigten Tabellen nachts entladen und dann prüfen, ob der Artikel (hier nehme ich den EAN, da eindeutig) bereits vorhanden ist.

Wenn ja -> update
Wenn nein -> insert

Wäre wahrscheinlich der einfachste Weg.

Was stored procedures angeht, würde ich wahrscheinlich daran kläglich scheitern, da zu wenig Ahnung (Programmiersprachen !!!!). Wie gesagt, ich habe die Beispiele im Buch schon nicht verstanden und soll dann obigen Inhalt auf 7 Tabellen verteilen (mit den entsprechenden Abhängigkeiten).

Eine andere Möglichkeit (die ich nicht unbedingt möchte) wäre das einlesen in eine Tabelle und dann ein manueller Import (PHP), wäre auch sehr einfach realisiert.

Aber das externe Bearbeiten reizt mich mehr, werde ich mal angehen.

(Jetzt ist dieser Thread aber im falschen Bereich :D )

wackeldackel
22-01-2005, 16:16
Hallo Cristoph,

ich habe mir deine Beschreibung durchgelesen :eek: und höre jetzt lieber auf am Rechner rumzuspielen und geh Schnee räumen. Damit komme ich wenigstens zurecht. ;) und am Ende kann sich das auch sehen lassen.

Hier schreibt ein Nebenbeiamrechnerfummelndenautoditaktischenihkkurs besuchendenmöchtegerntipper !!!!!!!!!!!!!!!!!!!!

Danke aber trotzdem, ich speichere das Teil und les es in 5 Jahren noch einmal durch.

Hans-Georg Normann
22-01-2005, 16:41
Dann sind wir ja schon wieder ein Stück weiter. Wenn ich das richtig verstanden habe, dann hast du Probleme, den Artikel in der Artikeldatei einzufügen bzw. Upzudaten. Das sollte aber ganz einfach sein, wenn man denn PostgreSql kennt. Da geht es bei mir schon los, arbeite normal mit Firebird und Stored Procedures verwende ich auch erst seit zwei Monaten. Aber was soll's?

in Firebird würde das so aussehen

....
#Artikrlnummer steht in einer Variablen V_ARTNR

SELECT COUNT(ART_NR)
FROM ARTIKEL_TAB
WHERE ART_NR = V_ARTNR
INTO :N_ARTIKEL;

IF N_ARTIKEL = 0 THEN BEGIN
#APPEND / INSERT
END ELSE BEGIN
#UPDATE
END;Ich hoffe, ich habe das halbwegs richtig wiedergegeben. Hilft dir das weiter?

Hans

wackeldackel
22-01-2005, 16:44
Abend Hans,

na das ist schon mal was. Werde mal versuchen, was zu bauen.

Falls ich Probleme habe, belagere ich dich einfach :)

Gruss Klaus

Hans-Georg Normann
22-01-2005, 17:15
Falls du Probleme hast, führen wir Firebird ein........... :D

Ich denke das wird schon. Schau dir vor allem die Variablendeklaration in stored procedures an und wie man die anspricht. Da bin ich jahrelang dran gescheitert. Habe das erst Dank IBExpert hinbekommen.

Hans

Christoph
24-01-2005, 12:00
Vielleicht nochmal eine Begründung, warum ich stored Procedures für dieses Problem für nicht so geeignet halte. Zwar kann man das damit lösen, es spricht aber folgendes dagegen:

1) Du brauchst diese Imporfunktion nur in einer einzigen Anwendung, nämlich dem Importprogramm. Das bedeutet, dass stored Procedures nicht nur unübersichtlicher sind (Du hast dann Deinen Code auf mehrere z.T. schwer zugängliche Stellen verteilt), sondern außerdam gar nichts vereinfachen, denn eine weiteres Importskript musst Du sowieso schreiben (das dann die Procedures aufruft).

2) Performancemäßig bringt das auch gar nichts, weil dein Importprogramm vermutlich sowieso auf dem Server läuft.

3) Vermutlich musst Du die Daten vor dem Import noch aufbereiten, was in einer dafür gut geeigneten Programmiersprache einfacher ist.

Ich sehe in diesem Anwendungsfall nicht einen einzigen Vorteil von stored Procedures (dass das ein cooles Feature ist bedeutet ja nicht, dass man es für alles anwenden sollte), lasse mich aber gerne vom Gegenteil belehren.

wackeldackel
24-01-2005, 19:49
Hallo Christoph,

habe mir das alles noch einmal durch den Kopf gehen lassen.

Das Problem ist, dass ich bei stored procedure sehr weit ausholen muss. Ich importiere die Daten in eine Lieferscheintabelle und muss dann 6 Tabellen prüfen, ob der Artikel nicht schon vorhanden ist, und wenn ja, ob die Werte den neuen Werten in der Lieferscheintabelle entsprechen. Werde ich nicht machen.

Meine beste Idee ist immer noch folgende:
(die gleiche Idee ,wie du hast)

Ich vergleiche mittels Bash Skript die Lieferscheindaten mit den entladenen Tabellen aus der Datenbank. Dazu muss ich ja nur prüfen, ob der EAN des Artikels in der Haupttabelle vorhanden ist.

Je nach Ergebnis mache ich halt den Update oder insert.


Gruss Klaus

Christoph
25-01-2005, 09:38
Ich vergleiche mittels Bash Skript die Lieferscheindaten mit den entladenen Tabellen aus der Datenbank. Dazu muss ich ja nur prüfen, ob der EAN des Artikels in der Haupttabelle vorhanden ist.

Warum bitte erst entladen und dann per bash (huh!) Script?
Schreibe ein Perl-Skript (oder Python oder ...), da kannst Du dann direkt SQL-Statements absetzen, z.B. so:



# testet ob Datensatz schon vorhanden
sub recordfound {
my $stmt;
$stmt = "select " . $spalten[$keyind] . " from $tabelle " .
"where " . $spalten[$keyind] . "=" . $werte[$keyind];
$sth = $dbh->prepare($stmt);
if (!$sth->execute) {
print $stmt . "\n";
print $dbh->errstr . "\n";
exit_rollback();
}
@row = $sth->fetchrow_array;
$sth->finish;
if (@row) {
return 1;
} else {
return 0;
}
}

Zur DBI Programmeirschnittstelle gibt's viele Tutorials im Internet.

wackeldackel
25-01-2005, 19:19
Hallo Christoph,

wäre auch ne Möglichkeit und voralllem einfacher im Ablauf.

Allerdings habe ich kaum Ahnung von Perl usw. Bisher habe ich nur die Bash mit awk und sed benötigt.
Deshalb versuche ich es erst einmal so und werde, sobald ich mich etwas eingelesen habe, dies vielleicht versuchen.

Allerdings fällt mir noch was ein. :cool:


Die Lieferscheine, die eingelesen werden, werden in ein separates Archivverzeichnis geschoben. Darum brauche ich nur zu prüfen, ob der Artikel (EAN) in einer dieser Dateien vorhanden ist.

Damit kann ich mein Bashscripting behalten und es funktioniert auch. :) :D

Oder nicht ?!?!?

Gruss Klaus

Christoph
25-01-2005, 19:50
Die Lieferscheine, die eingelesen werden, werden in ein separates Archivverzeichnis geschoben. Darum brauche ich nur zu prüfen, ob der Artikel (EAN) in einer dieser Dateien vorhanden ist.

Damit kann ich mein Bashscripting behalten und es funktioniert auch. :) :D

Oder nicht ?!?!?

Na ja, spätestens wenn Du 100.000 Lieferscheine hast, wirst Du die Daten zu einem einzelnen wohl erheblich schneller mit einem SQL-Statement in der Datenbank abfragen können als per grep und cut auf Dateiebene.

Wenn Du so argumentierst, dann brauchst Du die ganze Datenbank nicht, weil Du ja alles mit cut und grep wiederfinden kannst.

Warum sträubst Du dich so dagegen, dich mit irgendeiner Form der Datenbankprogrammierung zu befassen? Die Programmiersprache ist egal, das geht mit C, Perl, Python, Java, Tcl oder was auch immer. Wenn Du noch keine Sprache kennst, dann würde ich Python empfehlen, das ist für Anfänger am befriedigendsten.

Hans-Georg Normann
25-01-2005, 19:50
Die Lieferscheine, die eingelesen werden, werden in ein separates Archivverzeichnis geschoben. Darum brauche ich nur zu prüfen, ob der Artikel (EAN) in einer dieser Dateien vorhanden ist.Das ist aber nur dann sicher, solange du alle Lieferscheine archivierst. Solltest du mal aufräumen, sprich das Archiv teilweise löschen, könntest du ein Problem haben.

Du solltest das schon auf Datenbankebene klären, ob Artikel bereits vorhanden ist oder nicht. So schwer ist Python nun auch wieder nicht. Zu Perl kann ich nichts sagen.

Hans

wackeldackel
28-01-2005, 18:02
Hmmmmmhh!!!

Ich seh schon, ich habe hier keine Chance mit meinen "ausserordentlichen" Ideen.

Ich werde mal nen Blick auf Perl/Python riskieren. Zwischenzeitlich versuche ich es mal auf die einfachere Weise mit nem Bash Skript. :D :D

Solltet Ihr die nächsten zwei Jahre nix höre, habe ich das Zeug an die Wand getreten.

Gruss Klaus :)